diff --git a/session_1/slides_a.Rmd b/session_1/slides_a.Rmd
index 97c3b9b0e7637a58e3f2da7d735cf74bb85061d1..6d8f10a357754c3247d6c051a4338ca5703eaa6c 100644
--- a/session_1/slides_a.Rmd
+++ b/session_1/slides_a.Rmd
@@ -3,6 +3,8 @@ title: 'R#1: Introduction to R and RStudio'
 author: "Laurent Modolo [laurent.modolo@ens-lyon.fr](mailto:laurent.modolo@ens-lyon.fr)"
 date: "10 Oct 2019"
 output:
+  slidy_presentation:
+    highlight: tango
   beamer_presentation:
     theme: metropolis
     slide_level: 3
@@ -10,8 +12,6 @@ output:
     df_print: tibble
     highlight: tango
     latex_engine: xelatex
-  slidy_presentation:
-    highlight: tango
 ---
 ## R#1: Introduction to R and RStudio
 The goal of this practical is to familiarize yourself with R and the RStudio
@@ -39,13 +39,13 @@ The objectives of this session will be to:
   \end{column}
 \end{columns}
 
-# Some R background
+## Some R background
 
 \includegraphics[width=40pt]{img/Rlogo.png}
 is a programming language and free software environment for statistical
 computing and graphics supported by the *R Foundation for Statistical Computing*.
 
-# Some R background
+## Some R background
 
 \includegraphics[width=40pt]{img/Rlogo.png}
 
@@ -54,7 +54,7 @@ computing and graphics supported by the *R Foundation for Statistical Computing*
 - free and open-source implementation the S programming language
 - currently developed by the **R Development Core Team**.
 
-# Some R background
+## Some R background
 
 Reasons to use \includegraphics[width=40pt]{img/Rlogo.png}
 
@@ -66,11 +66,11 @@ Reasons to use \includegraphics[width=40pt]{img/Rlogo.png}
 - **3,087** available packages on http://www.bioconductor.org
 - **122,720** available repository on https://github.com/
 
-# Some R background
+## Some R background
 
 \includegraphics[width=\textwidth]{img/R_terminal.png}
 
-# RStudio, the R IDE
+## RStudio, the R IDE
 
 \begin{block}{IDR: Integrated development environment}
 application that provides {\bf comprehensive facilities} to computer programmers for
@@ -88,7 +88,7 @@ software development
 
 \includegraphics[width=\textwidth]{img/RStudio_console.png}
 
-# R as a calculator
+## R as a calculator
 
 - Add: `+`
 - Divide: `/`
@@ -97,7 +97,7 @@ software development
 - Exponents: `^` or `**`
 - Parentheses: `(`, `)`
 
-# R as a calculator
+## R as a calculator
 
 ```R
 1 + 100
diff --git a/session_1/slides_b.Rmd b/session_1/slides_b.Rmd
index 1831f7543252f7d4596f0d11d5892a3345b3900f..cb12a4b6d59a37a1bd9f48d62a33aaddfef52f0d 100644
--- a/session_1/slides_b.Rmd
+++ b/session_1/slides_b.Rmd
@@ -3,6 +3,10 @@ title: 'R#1: Introduction to R and RStudio'
 author: "Laurent Modolo [laurent.modolo@ens-lyon.fr](mailto:laurent.modolo@ens-lyon.fr)"
 date: "10 Oct 2019"
 output:
+  slidy_presentation:
+    highlight: tango
+  ioslides_presentation:
+    highlight: tango
   beamer_presentation:
     theme: metropolis
     slide_level: 3
@@ -10,10 +14,10 @@ output:
     df_print: tibble
     highlight: tango
     latex_engine: xelatex
-  slidy_presentation:
-    highlight: tango
 ---
+
 ## R#1: Introduction to R and RStudio
+
 The goal of this practical is to familiarize yourself with R and the RStudio
 environment.
 
@@ -194,7 +198,7 @@ unloadNamespace("tidyverse")
 sessionInfo()
 ```
 
-# Complex variable type
+## Complex variable type
 
 ## Vector (aka list)
 
@@ -285,7 +289,7 @@ all.equal(x, y)
 - Check the default vectors `letters` and `LETTERS`, rewrite your previous command using them.
 - Create a vector giving you the correspondence between small case letters and upper case letters.
 
-### Vector challenge
+## Vector challenge
 
 - use the `seq()` function to create a vector of even numbers
 ```R
@@ -295,7 +299,7 @@ seq(from=2, to=10, by=2)
 - Check the default vectors `letters` and `LETTERS`, rewrite your previous command using them.
 - Create a vector giving you the correspondence between small case letters and upper case letters.
 
-### Vector challenge
+## Vector challenge
 
 - use the `seq()` function to create a vector of even numbers
 ```R
@@ -305,7 +309,7 @@ seq(from=2, to=10, by=2)
 - Check the default vectors `letters` and `LETTERS`, rewrite your previous command using them.
 - Create a vector giving you the correspondence between small case letters and upper case letters.
 
-### Vector challenge
+## Vector challenge
 
 - use the `seq()` function to create a vector of even numbers
 - You can concatenate vector with `c(<VECTOR_1>, <VECTOR_2>)`, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.
@@ -316,7 +320,7 @@ typeof(c(1:5, "a", "b", "c"))
 - Check the default vectors `letters` and `LETTERS`, rewrite your previous command using them.
 - Create a vector giving you the correspondence between small case letters and upper case letters.
 
-### Vector challenge
+## Vector challenge
 
 - use the `seq()` function to create a vector of even numbers
 - You can concatenate vector with `c(<VECTOR_1>, <VECTOR_2>)`, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.
@@ -326,7 +330,7 @@ c(1:5, letters[1:3])
 ```
 - Create a vector giving you the correspondence between small case letters and upper case letters.
 
-### Vector challenge
+## Vector challenge
 
 - use the `seq()` function to create a vector of even numbers
 - You can concatenate vector with `c(<VECTOR_1>, <VECTOR_2>)`, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.
@@ -385,4 +389,38 @@ names(data_frame_example)
 ```R
 data_frame_example[2, 3]
 data_frame_example["numbers"]
+```
+
+## List
+
+In R `list` are multitypes object
+
+```R
+list(a = "test", b = 1)
+```
+
+\pause
+
+```R
+list(a = "test", b = 1:5)
+```
+
+\pause
+
+```R
+z <- list(
+  a = "test",
+  b = 1:5,
+  c = data.frame(numbers=1:26, letters=letters, LETTERS=LETTERS)
+)
+```
+
+\pause
+
+```R
+list(
+  a = "test",
+  b = 1:5,
+  c = z
+)
 ```
\ No newline at end of file
diff --git a/session_2/slides.Rmd b/session_2/slides.Rmd
index a39dbadfaf44240af321a9a2a58df550df10836c..3695714fcc65eb72a6d3d63f58284b34b8983fc0 100644
--- a/session_2/slides.Rmd
+++ b/session_2/slides.Rmd
@@ -3,6 +3,8 @@ title: "R#2: introduction to Tidyverse"
 author: "Laurent Modolo [laurent.modolo@ens-lyon.fr](mailto:laurent.modolo@ens-lyon.fr)"
 date: "24 Oct 2019"
 output:
+  slidy_presentation:
+    highlight: tango
   beamer_presentation:
     theme: metropolis
     slide_level: 3
@@ -10,8 +12,6 @@ output:
     df_print: tibble
     highlight: tango
     latex_engine: xelatex
-  slidy_presentation:
-    highlight: tango
 ---
 
 ```{r setup, include=FALSE, cache=TRUE}
@@ -188,26 +188,26 @@ ggplot(data = <DATA>) +
 - Make a scatterplot of `hwy` vs. `cyl`.
 - What happens if you make a scatterplot of `class` vs. `drive`? Why is the plot not useful?
 
-### Run `ggplot(data = mpg)`. What do you see?
+## Run `ggplot(data = mpg)`. What do you see?
 
 ```{r empty_plot, cache = TRUE, fig.width=8, fig.height=4.5}
 ggplot(data = new_mpg)
 ```
 
-### How many rows are in `new_mpg`? How many columns?
+## How many rows are in `new_mpg`? How many columns?
 
 ```{r size_of_mpg, cache = TRUE, fig.width=8, fig.height=4.5}
 new_mpg
 ```
 
-### Make a scatterplot of `hwy` vs. `cyl`.
+## Make a scatterplot of `hwy` vs. `cyl`.
 
 ```{r new_mpg_plot_b, cache = TRUE, fig.width=8, fig.height=4.5}
 ggplot(data = new_mpg) + 
   geom_point(mapping = aes(x = hwy, y = cyl))
 ```
 
-### What happens if you make a scatterplot of `class` vs. `drive`?
+## What happens if you make a scatterplot of `class` vs. `drive`?
 Why is the plot not useful?
 
 ```{r new_mpg_plot_c, cache = TRUE, fig.width=8, fig.height=4.5}
@@ -226,15 +226,14 @@ ggplot(data = mpg) +
              mapping = aes(x = displ, y = hwy), color = "red")
 ```
 
-###  Aesthetic mapping `color`
+##  Aesthetic mapping `color`
 
 ```{r new_mpg_plot_e, cache = TRUE, fig.width=8, fig.height=4.5}
 ggplot(data = mpg) + 
   geom_point(mapping = aes(x = displ, y = hwy, color = class))
 ```
 
-
-###  Aesthetic mappings
+##  Aesthetic mappings
 
 `ggplot2` will automatically assign a unique level of the aesthetic (here a unique color) to each unique value of the variable, a process known as scaling. `ggplot2` will also add a legend that explains which levels correspond to which values.
 
@@ -244,28 +243,28 @@ Try the following aesthetic:
 - `alpha`
 - `shape`
 
-###  Aesthetic mapping `size`
+##  Aesthetic mapping `size`
 
 ```{r new_mpg_plot_f, cache = TRUE, fig.width=8, fig.height=4.5, warning=FALSE}
 ggplot(data = mpg) + 
   geom_point(mapping = aes(x = displ, y = hwy, size = class))
 ```
 
-###  Aesthetic mapping `alpha`
+##  Aesthetic mapping `alpha`
 
 ```{r new_mpg_plot_g, cache = TRUE, fig.width=8, fig.height=4.5, warning=FALSE}
 ggplot(data = mpg) + 
   geom_point(mapping = aes(x = displ, y = hwy, alpha = class))
 ```
 
-###  Aesthetic mapping `shape`
+##  Aesthetic mapping `shape`
 
 ```{r new_mpg_plot_h, cache = TRUE, fig.width=8, fig.height=4.5, warning=FALSE}
 ggplot(data = mpg) + 
   geom_point(mapping = aes(x = displ, y = hwy, shape = class))
 ```
 
-###  Aesthetic
+##  Aesthetic
 
 You can also set the aesthetic properties of your geom manually. For example, we can make all of the points in our plot blue:
 
@@ -295,6 +294,7 @@ ggplot(data = mpg) +
   geom_point(mapping = aes(x = displ, y = hwy)) + 
   facet_wrap(~class)
 ```
+
 ## Facets
 
 ```{r new_mpg_plot_k, cache = TRUE, fig.width=8, fig.height=4.5}
diff --git a/web/slides_a.html b/web/slides_a.html
index f2ddbaea319b5c2c098242c9b55a8c07f158c5e4..f3df2bf54c619ee40eb694155905b78ed27ee89f 100644
--- a/web/slides_a.html
+++ b/web/slides_a.html
@@ -432,9 +432,8 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
   </p>
   <p class="date">10 Oct 2019</p>
 </div>
-<div class="slide section level1">
-
-<h2 id="r1-introduction-to-r-and-rstudio">R#1: Introduction to R and RStudio</h2>
+<div id="r1-introduction-to-r-and-rstudio" class="slide section level2">
+<h1>R#1: Introduction to R and RStudio</h1>
 <p>The goal of this practical is to familiarize yourself with R and the RStudio environment.</p>
 <p>The objectives of this session will be to:</p>
 <ul>
@@ -445,14 +444,16 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 <li>Call functions</li>
 <li>Manage packages</li>
 </ul>
-<h2 id="acknowledgments">Acknowledgments</h2>
+</div>
+<div id="acknowledgments" class="slide section level2">
+<h1>Acknowledgments</h1>
 
 </div>
-<div id="some-r-background" class="slide section level1">
+<div id="some-r-background" class="slide section level2">
 <h1>Some R background</h1>
 <p> is a programming language and free software environment for statistical computing and graphics supported by the <em>R Foundation for Statistical Computing</em>.</p>
 </div>
-<div id="some-r-background-1" class="slide section level1">
+<div id="some-r-background-1" class="slide section level2">
 <h1>Some R background</h1>
 <p></p>
 <ul>
@@ -462,7 +463,7 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 <li>currently developed by the <strong>R Development Core Team</strong>.</li>
 </ul>
 </div>
-<div id="some-r-background-2" class="slide section level1">
+<div id="some-r-background-2" class="slide section level2">
 <h1>Some R background</h1>
 <p>Reasons to use </p>
 <ul>
@@ -474,23 +475,27 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 <li><p><strong>122,720</strong> available repository on <a href="https://github.com/" class="uri">https://github.com/</a></p></li>
 </ul>
 </div>
-<div id="some-r-background-3" class="slide section level1">
+<div id="some-r-background-3" class="slide section level2">
 <h1>Some R background</h1>
 <p></p>
 </div>
-<div id="rstudio-the-r-ide" class="slide section level1">
+<div id="rstudio-the-r-ide" class="slide section level2">
 <h1>RStudio, the R IDE</h1>
 
 <ul>
 <li>free</li>
 <li>open source</li>
 </ul>
-<h2 id="an-interface">An interface</h2>
+</div>
+<div id="an-interface" class="slide section level2">
+<h1>An interface</h1>
 <p></p>
-<h2 id="the-same-console-as-before">The same console as before</h2>
+</div>
+<div id="the-same-console-as-before" class="slide section level2">
+<h1>The same console as before</h1>
 <p></p>
 </div>
-<div id="r-as-a-calculator" class="slide section level1">
+<div id="r-as-a-calculator" class="slide section level2">
 <h1>R as a calculator</h1>
 <ul>
 <li>Add: <code>+</code></li>
@@ -501,7 +506,7 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 <li>Parentheses: <code>(</code>, <code>)</code></li>
 </ul>
 </div>
-<div id="r-as-a-calculator-1" class="slide section level1">
+<div id="r-as-a-calculator-1" class="slide section level2">
 <h1>R as a calculator</h1>
 <div class="sourceCode" id="cb1"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1"></a><span class="dv">1</span> <span class="op">+</span><span class="st"> </span><span class="dv">100</span></span>
 <span id="cb1-2"><a href="#cb1-2"></a><span class="dv">1</span> <span class="op">+</span></span></code></pre></div>
@@ -517,7 +522,9 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 
 <p><code>2e-4</code> is shorthand for <code>2 * 10^(-4)</code></p>
 <div class="sourceCode" id="cb6"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb6-1"><a href="#cb6-1"></a><span class="fl">5e3</span></span></code></pre></div>
-<h2 id="mathematical-functions">Mathematical functions</h2>
+</div>
+<div id="mathematical-functions" class="slide section level2">
+<h1>Mathematical functions</h1>
 <div class="sourceCode" id="cb7"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">log</span>(<span class="dv">1</span>)  <span class="co"># natural logarithm</span></span></code></pre></div>
 
 <div class="sourceCode" id="cb8"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">log10</span>(<span class="dv">10</span>) <span class="co"># base-10 logarithm</span></span></code></pre></div>
@@ -527,7 +534,9 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 <p>Compute the factorial of <code>9</code></p>
 
 <div class="sourceCode" id="cb10"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">factorial</span>(<span class="dv">9</span>)</span></code></pre></div>
-<h2 id="comparing-things">Comparing things</h2>
+</div>
+<div id="comparing-things" class="slide section level2">
+<h1>Comparing things</h1>
 <p>equality (note two equal signs read as “is equal to”)</p>
 <div class="sourceCode" id="cb11"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb11-1"><a href="#cb11-1"></a><span class="dv">1</span> <span class="op">==</span><span class="st"> </span><span class="dv">1</span></span></code></pre></div>
 
@@ -542,13 +551,19 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 
 <p>greater than</p>
 <div class="sourceCode" id="cb15"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb15-1"><a href="#cb15-1"></a><span class="dv">1</span> <span class="op">&gt;</span><span class="st"> </span><span class="dv">0</span></span></code></pre></div>
-<h2 id="variables-and-assignment">Variables and assignment</h2>
+</div>
+<div id="variables-and-assignment" class="slide section level2">
+<h1>Variables and assignment</h1>
 <p><code>&lt;-</code> is the assignment operator in R. (read as left member take right member value)</p>
 <div class="sourceCode" id="cb16"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb16-1"><a href="#cb16-1"></a>x &lt;-<span class="st"> </span><span class="dv">1</span><span class="op">/</span><span class="dv">40</span></span></code></pre></div>
 <div class="sourceCode" id="cb17"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb17-1"><a href="#cb17-1"></a>x</span></code></pre></div>
-<h2 id="the-environment">The environment</h2>
+</div>
+<div id="the-environment" class="slide section level2">
+<h1>The environment</h1>
 <p></p>
-<h2 id="variables-and-assignment-1">Variables and assignment</h2>
+</div>
+<div id="variables-and-assignment-1" class="slide section level2">
+<h1>Variables and assignment</h1>
 <div class="sourceCode" id="cb18"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb18-1"><a href="#cb18-1"></a><span class="kw">log</span>(x)</span>
 <span id="cb18-2"><a href="#cb18-2"></a>x &lt;-<span class="st"> </span><span class="dv">100</span></span>
 <span id="cb18-3"><a href="#cb18-3"></a><span class="kw">log</span>(x)</span></code></pre></div>
@@ -558,7 +573,9 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 
 <div class="sourceCode" id="cb20"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb20-1"><a href="#cb20-1"></a>z &lt;-<span class="st"> &quot;x&quot;</span></span>
 <span id="cb20-2"><a href="#cb20-2"></a>x <span class="op">+</span><span class="st"> </span>z</span></code></pre></div>
-<h2 id="variables-and-assignment-2">Variables and assignment</h2>
+</div>
+<div id="variables-and-assignment-2" class="slide section level2">
+<h1>Variables and assignment</h1>
 <p>Variable names can contain letters, numbers, underscores and periods.</p>
 <p>They cannot start with a number nor contain spaces at all.</p>
 <p>Different people use different conventions for long variable names, these include</p>
@@ -568,7 +585,9 @@ Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-ly
 <p>What you use is up to you, but be consistent.</p>
 
 <p>It is also possible to use the <code>=</code> operator for assignment but <strong>don’t do it !</strong></p>
-<h2 id="variables-and-assignment-3">Variables and assignment</h2>
+</div>
+<div id="variables-and-assignment-3" class="slide section level2">
+<h1>Variables and assignment</h1>
 <p>Which of the following are valid R variable names?</p>
 <pre><code>min_height
 max.height
@@ -579,7 +598,9 @@ min-length
 2widths
 celsius2kelvin</code></pre>
 <p><strong><a href="http://perso.ens-lyon.fr/laurent.modolo/R/1_a" class="uri">http://perso.ens-lyon.fr/laurent.modolo/R/1_a</a></strong></p>
-<h2 id="functions-are-also-variables">Functions are also variables</h2>
+</div>
+<div id="functions-are-also-variables" class="slide section level2">
+<h1>Functions are also variables</h1>
 <div class="sourceCode" id="cb23"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb23-1"><a href="#cb23-1"></a>logarithm &lt;-<span class="st"> </span>log</span></code></pre></div>
 
 <p>A R function can have different arguments</p>
@@ -594,18 +615,24 @@ celsius2kelvin</code></pre>
 <div class="sourceCode" id="cb25"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb25-1"><a href="#cb25-1"></a><span class="kw">help</span>(log)</span></code></pre></div>
 
 <div class="sourceCode" id="cb26"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb26-1"><a href="#cb26-1"></a>?log</span></code></pre></div>
-<h2 id="various-output">Various output</h2>
+</div>
+<div id="various-output" class="slide section level2">
+<h1>Various output</h1>
 <p></p>
-<h2 id="functions-are-also-variables-1">Functions are also variables</h2>
+</div>
+<div id="functions-are-also-variables-1" class="slide section level2">
+<h1>Functions are also variables</h1>
 <p>Test that your <code>logarithm</code> function can work in base 10</p>
 
 <div class="sourceCode" id="cb27"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb27-1"><a href="#cb27-1"></a><span class="dv">10</span><span class="op">^</span><span class="kw">logarithm</span>(<span class="dv">12</span>, <span class="dt">base =</span> <span class="dv">10</span>)</span></code></pre></div>
-<h2 id="functions-are-also-variables-2">Functions are also variables</h2>
+</div>
+<div id="functions-are-also-variables-2" class="slide section level2">
+<h1>Functions are also variables</h1>
 <p>We can also define our own function with</p>
-<div class="sourceCode" id="cb28"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb28-1"><a href="#cb28-1"></a>function_name &lt;-<span class="st"> </span><span class="cf">function</span>(a, b){</span>
-<span id="cb28-2"><a href="#cb28-2"></a>  result_<span class="dv">1</span> &lt;-<span class="st"> </span><span class="kw">operation1</span>(a, b)</span>
-<span id="cb28-3"><a href="#cb28-3"></a>  result_<span class="dv">2</span> &lt;-<span class="st"> </span><span class="kw">operation2</span>(result_<span class="dv">1</span>, b)</span>
-<span id="cb28-4"><a href="#cb28-4"></a>  <span class="kw">return</span>(result_<span class="dv">2</span>)</span>
+<div class="sourceCode" id="cb28"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb28-1"><a href="#cb28-1"></a><span class="op">&lt;</span>FUNCTION_NAME<span class="op">&gt;</span><span class="st"> </span><span class="er">&lt;</span><span class="op">-</span><span class="st"> </span><span class="cf">function</span>(a, b){</span>
+<span id="cb28-2"><a href="#cb28-2"></a>  <span class="op">&lt;</span>RESULT_<span class="dv">1</span><span class="op">&gt;</span><span class="st"> </span><span class="er">&lt;</span><span class="op">-</span><span class="st"> </span><span class="er">&lt;</span>OPERATION_<span class="dv">1</span><span class="op">&gt;</span>(a, b)</span>
+<span id="cb28-3"><a href="#cb28-3"></a>  <span class="op">&lt;</span>RESULT_<span class="dv">2</span><span class="op">&gt;</span><span class="st"> </span><span class="er">&lt;</span><span class="op">-</span><span class="st"> </span><span class="er">&lt;</span>OPERATION_<span class="dv">2</span><span class="op">&gt;</span>(<span class="op">&lt;</span>RESULT_<span class="dv">1</span><span class="op">&gt;</span>, b)</span>
+<span id="cb28-4"><a href="#cb28-4"></a>  <span class="kw">return</span>(<span class="op">&lt;</span>RESULT_<span class="dv">2</span><span class="op">&gt;</span>)</span>
 <span id="cb28-5"><a href="#cb28-5"></a>}</span></code></pre></div>
 
 <p>write a function to test the base of the logarithm function</p>
diff --git a/web/slides_b.html b/web/slides_b.html
new file mode 100644
index 0000000000000000000000000000000000000000..9b17bf1d6c952adfcfa8caec7331c7498a2272ef
--- /dev/null
+++ b/web/slides_b.html
@@ -0,0 +1,725 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Content-Style-Type" content="text/css" />
+  <meta name="generator" content="pandoc" />
+  <meta name="author" content="Laurent Modolo laurent.modolo@ens-lyon.fr" />
+  <meta name="date" content="2019-10-10" />
+  <title>R#1: Introduction to R and RStudio</title>
+  <style type="text/css">code{white-space: pre;}</style>
+  <style type="text/css">
+pre > code.sourceCode { white-space: pre; position: relative; }
+pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
+pre > code.sourceCode > span:empty { height: 1.2em; }
+code.sourceCode > span { color: inherit; text-decoration: inherit; }
+div.sourceCode { margin: 1em 0; }
+pre.sourceCode { margin: 0; }
+@media screen {
+div.sourceCode { overflow: auto; }
+}
+@media print {
+pre > code.sourceCode { white-space: pre-wrap; }
+pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
+}
+pre.numberSource code
+  { counter-reset: source-line 0; }
+pre.numberSource code > span
+  { position: relative; left: -4em; counter-increment: source-line; }
+pre.numberSource code > span > a:first-child::before
+  { content: counter(source-line);
+    position: relative; left: -1em; text-align: right; vertical-align: baseline;
+    border: none; display: inline-block;
+    -webkit-touch-callout: none; -webkit-user-select: none;
+    -khtml-user-select: none; -moz-user-select: none;
+    -ms-user-select: none; user-select: none;
+    padding: 0 4px; width: 4em;
+    color: #aaaaaa;
+  }
+pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
+div.sourceCode
+  {  background-color: #f8f8f8; }
+@media screen {
+pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
+}
+code span.al { color: #ef2929; } /* Alert */
+code span.an { color: #8f5902; font-weight: bold; font-style: italic; } /* Annotation */
+code span.at { color: #c4a000; } /* Attribute */
+code span.bn { color: #0000cf; } /* BaseN */
+code span.cf { color: #204a87; font-weight: bold; } /* ControlFlow */
+code span.ch { color: #4e9a06; } /* Char */
+code span.cn { color: #000000; } /* Constant */
+code span.co { color: #8f5902; font-style: italic; } /* Comment */
+code span.cv { color: #8f5902; font-weight: bold; font-style: italic; } /* CommentVar */
+code span.do { color: #8f5902; font-weight: bold; font-style: italic; } /* Documentation */
+code span.dt { color: #204a87; } /* DataType */
+code span.dv { color: #0000cf; } /* DecVal */
+code span.er { color: #a40000; font-weight: bold; } /* Error */
+code span.ex { } /* Extension */
+code span.fl { color: #0000cf; } /* Float */
+code span.fu { color: #000000; } /* Function */
+code span.im { } /* Import */
+code span.in { color: #8f5902; font-weight: bold; font-style: italic; } /* Information */
+code span.kw { color: #204a87; font-weight: bold; } /* Keyword */
+code span.op { color: #ce5c00; font-weight: bold; } /* Operator */
+code span.ot { color: #8f5902; } /* Other */
+code span.pp { color: #8f5902; font-style: italic; } /* Preprocessor */
+code span.sc { color: #000000; } /* SpecialChar */
+code span.ss { color: #4e9a06; } /* SpecialString */
+code span.st { color: #4e9a06; } /* String */
+code span.va { color: #000000; } /* Variable */
+code span.vs { color: #4e9a06; } /* VerbatimString */
+code span.wa { color: #8f5902; font-weight: bold; font-style: italic; } /* Warning */
+  </style>
+  <style type="text/css">
+body
+{
+margin: 0 0 0 0;
+padding: 0 0 0 0;
+width: 100%;
+height: 100%;
+color: black;
+background-color: white;
+font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
+font-size: 14pt;
+}
+div.toolbar {
+position: fixed; z-index: 200;
+top: auto; bottom: 0; left: 0; right: 0;
+height: 1.2em; text-align: right;
+padding-left: 1em;
+padding-right: 1em; font-size: 60%;
+color: DimGray;
+background-color: rgb(240,240,240);
+border-top: solid 1px rgb(180,180,180);
+}
+div.toolbar span.copyright {
+color: DimGray;
+margin-left: 0.5em;
+}
+div.initial_prompt {
+position: absolute;
+z-index: 1000;
+bottom: 1.2em;
+width: 100%;
+background-color: rgb(200,200,200);
+opacity: 0.35;
+background-color: rgb(200,200,200, 0.35);
+cursor: pointer;
+}
+div.initial_prompt p.help {
+text-align: center;
+}
+div.initial_prompt p.close {
+text-align: right;
+font-style: italic;
+}
+div.slidy_toc {
+position: absolute;
+z-index: 300;
+width: 60%;
+max-width: 30em;
+height: 30em;
+overflow: auto;
+top: auto;
+right: auto;
+left: 4em;
+bottom: 4em;
+padding: 1em;
+background: rgb(240,240,240);
+border-style: solid;
+border-width: 2px;
+font-size: 60%;
+}
+div.slidy_toc .toc_heading {
+text-align: center;
+width: 100%;
+margin: 0;
+margin-bottom: 1em;
+border-bottom-style: solid;
+border-bottom-color: rgb(180,180,180);
+border-bottom-width: 1px;
+}
+div.slide {
+z-index: 20;
+margin: 0 0 0 0;
+padding-top: 0;
+padding-bottom: 0;
+padding-left: 20px;
+padding-right: 20px;
+border-width: 0;
+clear: both;
+top: 0;
+bottom: 0;
+left: 0;
+right: 0;
+line-height: 120%;
+background-color: transparent;
+}
+div.background {
+display: none;
+}
+div.handout {
+margin-left: 20px;
+margin-right: 20px;
+}
+div.slide.titlepage {
+text-align: center;
+}
+div.slide.titlepage h1 {
+padding-top: 10%;
+margin-right: 0;
+}
+div.slide h1 {
+padding-left: 0;
+padding-right: 20pt;
+padding-top: 4pt;
+padding-bottom: 4pt;
+margin-top: 0;
+margin-left: 0;
+margin-right: 60pt;
+margin-bottom: 0.5em;
+display: block; font-size: 160%;
+line-height: 1.2em;
+background: transparent;
+}
+@media screen and (max-device-width: 1024px)
+{
+div.slide { font-size: 100%; }
+}
+@media screen and (max-device-width: 800px)
+{
+div.slide { font-size: 200%; }
+div.slidy_toc {
+top: 1em;
+left: 1em;
+right: auto;
+width: 80%;
+font-size: 180%;
+}
+}
+div.toc-heading {
+width: 100%;
+border-bottom: solid 1px rgb(180,180,180);
+margin-bottom: 1em;
+text-align: center;
+}
+img {
+image-rendering: optimize-quality;
+}
+pre {
+font-size: 80%;
+font-weight: bold;
+line-height: 120%;
+padding-top: 0.2em;
+padding-bottom: 0.2em;
+padding-left: 1em;
+padding-right: 1em;
+border-style: solid;
+border-left-width: 1em;
+border-top-width: thin;
+border-right-width: thin;
+border-bottom-width: thin;
+border-color: #95ABD0;
+color: #00428C;
+background-color: #E4E5E7;
+}
+li pre { margin-left: 0; }
+blockquote { font-style: italic }
+img { background-color: transparent }
+p.copyright { font-size: smaller }
+.center { text-align: center }
+.footnote { font-size: smaller; margin-left: 2em; }
+a img { border-width: 0; border-style: none }
+a:visited { color: navy }
+a:link { color: navy }
+a:hover { color: red; text-decoration: underline }
+a:active { color: red; text-decoration: underline }
+a {text-decoration: none}
+.toolbar a:link {color: blue}
+.toolbar a:visited {color: blue}
+.toolbar a:active {color: red}
+.toolbar a:hover {color: red}
+ul { list-style-type: square; }
+ul ul { list-style-type: disc; }
+ul ul ul { list-style-type: circle; }
+ul ul ul ul { list-style-type: disc; }
+li { margin-left: 0.5em; margin-top: 0.5em; }
+li li { font-size: 85%; font-style: italic }
+li li li { font-size: 85%; font-style: normal }
+div dt
+{
+margin-left: 0;
+margin-top: 1em;
+margin-bottom: 0.5em;
+font-weight: bold;
+}
+div dd
+{
+margin-left: 2em;
+margin-bottom: 0.5em;
+}
+p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
+margin-left: 1em;
+margin-right: 1em;
+}
+p.subhead { font-weight: bold; margin-top: 2em; }
+.smaller { font-size: smaller }
+.bigger { font-size: 130% }
+td,th { padding: 0.2em }
+ul {
+margin: 0.5em 1.5em 0.5em 1.5em;
+padding: 0;
+}
+ol {
+margin: 0.5em 1.5em 0.5em 1.5em;
+padding: 0;
+}
+ul { list-style-type: square; }
+ul ul { list-style-type: disc; }
+ul ul ul { list-style-type: circle; }
+ul ul ul ul { list-style-type: disc; }
+ul li { list-style: square;
+margin: 0.1em 0em 0.6em 0;
+padding: 0 0 0 0;
+line-height: 140%;
+}
+ol li { margin: 0.1em 0em 0.6em 1.5em;
+padding: 0 0 0 0px;
+line-height: 140%;
+list-style-type: decimal;
+}
+li ul li { font-size: 85%; font-style: italic;
+list-style-type: disc;
+background: transparent;
+padding: 0 0 0 0;
+}
+li li ul li { font-size: 85%; font-style: normal;
+list-style-type: circle;
+background: transparent;
+padding: 0 0 0 0;
+}
+li li li ul li {
+list-style-type: disc;
+background: transparent;
+padding: 0 0 0 0;
+}
+li ol li {
+list-style-type: decimal;
+}
+li li ol li {
+list-style-type: decimal;
+}
+
+ol.outline li:hover { cursor: pointer }
+ol.outline li.nofold:hover { cursor: default }
+ul.outline li:hover { cursor: pointer }
+ul.outline li.nofold:hover { cursor: default }
+ol.outline { list-style:decimal; }
+ol.outline ol { list-style-type:lower-alpha }
+ol.outline li.nofold {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAIACAMzMzOvr/ywAAAAACQAJAAACD4SPoRvG614Dctb4MEMcFAA7) no-repeat 0px 0.5em;
+}
+ol.outline li.unfolded {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAMPD/8zMzOvr/////ywAAAAACQAJAAACEYyPoivG614LAlg7ZZbxoR8UADs=) no-repeat 0px 0.5em;
+}
+ol.outline li.folded {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAMPD/8zMzOvr/////ywAAAAACQAJAAACFIyPoiu2sJyCyoF7W3hxz850CFIAADs=) no-repeat 0px 0.5em;
+}
+ol.outline li.unfolded:hover {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAAAAAAAA/8PD/////ywAAAAACQAJAAACEYSPoivG614DIlg7ZZbxoQ8UADs=) no-repeat 0px 0.5em;
+}
+ol.outline li.folded:hover {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAAAAAAAA/8PD/////ywAAAAACQAJAAACFISPoiu2sZyCyoV7G3hxz850CFIAADs=) no-repeat 0px 0.5em;
+}
+ul.outline li.nofold {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAIACAMzMzOvr/ywAAAAACQAJAAACD4SPoRvG614Dctb4MEMcFAA7) no-repeat 0px 0.5em;
+}
+ul.outline li.unfolded {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAMPD/8zMzOvr/////ywAAAAACQAJAAACEYyPoivG614LAlg7ZZbxoR8UADs=) no-repeat 0px 0.5em;
+}
+ul.outline li.folded {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAMPD/8zMzOvr/////ywAAAAACQAJAAACFIyPoiu2sJyCyoF7W3hxz850CFIAADs=) no-repeat 0px 0.5em;
+}
+ul.outline li.unfolded:hover {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAAAAAAAA/8PD/////ywAAAAACQAJAAACEYSPoivG614DIlg7ZZbxoQ8UADs=) no-repeat 0px 0.5em;
+}
+ul.outline li.folded:hover {
+padding: 0 0 0 20px;
+background: transparent url(data:image/gif;base64,R0lGODdhCQAJAKEDAAAAAAAA/8PD/////ywAAAAACQAJAAACFISPoiu2sZyCyoV7G3hxz850CFIAADs=) no-repeat 0px 0.5em;
+}
+
+a.titleslide { font-weight: bold; font-style: italic }
+
+img.hidden { display: none; visibility: hidden }
+div.initial_prompt { display: none; visibility: hidden }
+div.slide {
+visibility: visible;
+position: inherit;
+}
+div.handout {
+border-top-style: solid;
+border-top-width: thin;
+border-top-color: black;
+}
+@media screen {
+.hidden { display: none; visibility: visible }
+div.slide.hidden { display: block; visibility: visible }
+div.handout.hidden { display: block; visibility: visible }
+div.background { display: none; visibility: hidden }
+body.single_slide div.initial_prompt { display: block; visibility: visible }
+body.single_slide div.background { display: block; visibility: visible }
+body.single_slide div.background.hidden { display: none; visibility: hidden }
+body.single_slide .invisible { visibility: hidden }
+body.single_slide .hidden { display: none; visibility: hidden }
+body.single_slide div.slide { position: absolute }
+body.single_slide div.handout { display: none; visibility: hidden }
+}
+@media print {
+.hidden { display: block; visibility: visible }
+div.slide pre { font-size: 60%; padding-left: 0.5em; }
+div.toolbar { display: none; visibility: hidden; }
+div.slidy_toc { display: none; visibility: hidden; }
+div.background { display: none; visibility: hidden; }
+div.slide { page-break-before: always }
+
+div.slide.first-slide { page-break-before: avoid }
+}
+
+
+.jslider table {
+margin-left: 0em;
+margin-right: 0em;
+}
+
+table.dataTable, .shiny-datatable-output div {
+font-size: 14pt;
+}
+
+.dataTables_info, .dataTables_paginate {
+font-size: 19px;
+}
+
+pre.sourceCode, code.sourceCode {
+font-size: 80%;
+}
+
+label, button, input, select, textarea {
+font-size: 14pt;
+}
+
+ul.nav, ul.nav li {
+list-style-type: none;
+}
+</style>
+  <script src="data:application/javascript;base64,Lyogc2xpZHkuanMKCiAgIENvcHlyaWdodCAoYykgMjAwNS0yMDEzIFczQyAoTUlULCBFUkNJTSwgS2VpbyksIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgIFczQyBsaWFiaWxpdHksIHRyYWRlbWFyaywgZG9jdW1lbnQgdXNlIGFuZCBzb2Z0d2FyZSBsaWNlbnNpbmcKICAgcnVsZXMgYXBwbHksIHNlZToKCiAgIGh0dHA6Ly93d3cudzMub3JnL0NvbnNvcnRpdW0vTGVnYWwvY29weXJpZ2h0LWRvY3VtZW50cwogICBodHRwOi8vd3d3LnczLm9yZy9Db25zb3J0aXVtL0xlZ2FsL2NvcHlyaWdodC1zb2Z0d2FyZQoKICAgRGVmaW5lcyBzaW5nbGUgbmFtZSAidzNjX3NsaWR5IiBpbiBnbG9iYWwgbmFtZXNwYWNlCiAgIEFkZHMgZXZlbnQgaGFuZGxlcnMgd2l0aG91dCB0cmFtcGxpbmcgb24gYW55IG90aGVycwoqLwoKLy8gdGhlIHNsaWR5IG9iamVjdCBpbXBsZW1lbnRhdGlvbgp2YXIgdzNjX3NsaWR5ID0gewogIC8vIGNsYXNzaWZ5IHdoaWNoIGtpbmQgb2YgYnJvd3NlciB3ZSdyZSBydW5uaW5nIHVuZGVyCiAgbnNfcG9zOiAodHlwZW9mIHdpbmRvdy5wYWdlWU9mZnNldCE9J3VuZGVmaW5lZCcpLAogIGtodG1sOiAoKG5hdmlnYXRvci51c2VyQWdlbnQpLmluZGV4T2YoIktIVE1MIikgPj0gMCA/IHRydWUgOiBmYWxzZSksCiAgb3BlcmE6ICgobmF2aWdhdG9yLnVzZXJBZ2VudCkuaW5kZXhPZigiT3BlcmEiKSA+PSAwID8gdHJ1ZSA6IGZhbHNlKSwKICBpcGFkOiAoKG5hdmlnYXRvci51c2VyQWdlbnQpLmluZGV4T2YoImlQYWQiKSA+PSAwID8gdHJ1ZSA6IGZhbHNlKSwKICBpcGhvbmU6ICgobmF2aWdhdG9yLnVzZXJBZ2VudCkuaW5kZXhPZigiaVBob25lIikgPj0gMCA/IHRydWUgOiBmYWxzZSksCiAgYW5kcm9pZDogKChuYXZpZ2F0b3IudXNlckFnZW50KS5pbmRleE9mKCJBbmRyb2lkIikgPj0gMCA/IHRydWUgOiBmYWxzZSksCiAgaWU6ICh0eXBlb2YgZG9jdW1lbnQuYWxsICE9ICJ1bmRlZmluZWQiICYmICF0aGlzLm9wZXJhKSwKICBpZTY6ICghdGhpcy5uc19wb3MgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCJNU0lFIDYiKSAhPSAtMSksCiAgaWU3OiAoIXRoaXMubnNfcG9zICYmIG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZigiTVNJRSA3IikgIT0gLTEpLAogIGllODogKCF0aGlzLm5zX3BvcyAmJiBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoIk1TSUUgOCIpICE9IC0xKSwKICBpZTk6ICghdGhpcy5uc19wb3MgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCJNU0lFIDkiKSAhPSAtMSksCgogIC8vIGRhdGEgZm9yIHN3aXBlIGFuZCBkb3VibGUgdGFwIGRldGVjdGlvbiBvbiB0b3VjaCBzY3JlZW5zCiAgbGFzdF90YXA6IDAsCiAgcHJldl90YXA6IDAsCiAgc3RhcnRfeDogMCwKICBzdGFydF95OiAwLAogIGRlbHRhX3g6IDAsCiAgZGVsdGFfeTogMCwKCiAgLy8gYXJlIHdlIHJ1bm5pbmcgYXMgWEhUTUw/IChkb2Vzbid0IHdvcmsgb24gT3BlcmEpCiAgaXNfeGh0bWw6IC94bWwvLnRlc3QoZG9jdW1lbnQuY29udGVudFR5cGUpLAoKICBzbGlkZV9udW1iZXI6IDAsIC8vIGludGVnZXIgc2xpZGUgY291bnQ6IDAsIDEsIDIsIC4uLgogIHNsaWRlX251bWJlcl9lbGVtZW50OiBudWxsLCAvLyBlbGVtZW50IGNvbnRhaW5pbmcgc2xpZGUgbnVtYmVyCiAgc2xpZGVzOiBbXSwgLy8gc2V0IHRvIGFycmF5IG9mIHNsaWRlIGRpdidzCiAgbm90ZXM6IFtdLCAvLyBzZXQgdG8gYXJyYXkgb2YgaGFuZG91dCBkaXYncwogIGJhY2tncm91bmRzOiBbXSwgLy8gc2V0IHRvIGFycmF5IG9mIGJhY2tncm91bmQgZGl2J3MKICBvYnNlcnZlcnM6IFtdLCAvLyBsaXN0IG9mIG9ic2VydmVyIGZ1bmN0aW9ucwogIHRvb2xiYXI6IG51bGwsIC8vIGVsZW1lbnQgY29udGFpbmluZyB0b29sYmFyCiAgdGl0bGU6IG51bGwsIC8vIGRvY3VtZW50IHRpdGxlCiAgbGFzdF9zaG93bjogbnVsbCwgLy8gbGFzdCBpbmNyZW1lbnRhbGx5IHNob3duIGl0ZW0KICBlb3M6IG51bGwsICAvLyBzcGFuIGVsZW1lbnQgZm9yIGVuZCBvZiBzbGlkZSBpbmRpY2F0b3IKICB0b2M6IG51bGwsIC8vIHRhYmxlIG9mIGNvbnRlbnRzCiAgb3V0bGluZTogbnVsbCwgLy8gb3V0bGluZSBlbGVtZW50IHdpdGggdGhlIGZvY3VzCiAgc2VsZWN0ZWRfdGV4dF9sZW46IDAsIC8vIGxlbmd0aCBvZiBkcmFnIHNlbGVjdGlvbiBvbiBkb2N1bWVudAogIHZpZXdfYWxsOiAwLCAgLy8gMSB0byB2aWV3IGFsbCBzbGlkZXMgKyBoYW5kb3V0cwogIHdhbnRfdG9vbGJhcjogdHJ1ZSwgIC8vIHVzZXIgcHJlZmVyZW5jZSB0byBzaG93L2hpZGUgdG9vbGJhcgogIG1vdXNlX2NsaWNrX2VuYWJsZWQ6IHRydWUsIC8vIGVuYWJsZXMgbGVmdCBjbGljayBmb3IgbmV4dCBzbGlkZQogIHNjcm9sbF9oYWNrOiAwLCAvLyBJRSB3b3JrIGFyb3VuZCBmb3IgcG9zaXRpb246IGZpeGVkCiAgZGlzYWJsZV9zbGlkZV9jbGljazogZmFsc2UsICAvLyB1c2VkIGJ5IGNsaWNrZWQgYW5jaG9ycwoKICBsYW5nOiAiZW4iLCAvLyB1cGRhdGVkIHRvIGxhbmd1YWdlIHNwZWNpZmllZCBieSBodG1sIGZpbGUKCiAgaGVscF9hbmNob3I6IG51bGwsIC8vIHVzZWQgZm9yIGtleWJvYXJkIGZvY3VzIGhhY2sgaW4gc2hvd1Rvb2xiYXIoKQogIGhlbHBfcGFnZTogImh0dHA6Ly93d3cudzMub3JnL1RhbGtzL1Rvb2xzL1NsaWR5Mi9oZWxwL2hlbHAuaHRtbCIsCiAgaGVscF90ZXh0OiAiTmF2aWdhdGUgd2l0aCBtb3VzZSBjbGljaywgc3BhY2UgYmFyLCBDdXJzb3IgTGVmdC9SaWdodCwgIiArCiAgICAgICAgICAgICAib3IgUGcgVXAgYW5kIFBnIERuLiBVc2UgUyBhbmQgQiB0byBjaGFuZ2UgZm9udCBzaXplLiIsCgogIHNpemVfaW5kZXg6IDAsCiAgc2l6ZV9hZGp1c3RtZW50OiAwLAogIHNpemVzOiAgbmV3IEFycmF5KCIxMHB0IiwgIjEycHQiLCAiMTRwdCIsICIxNnB0IiwgIjE4cHQiLCAiMjBwdCIsCiAgICAgICAgICAgICAgICAgICAgIjIycHQiLCAiMjRwdCIsICIyNnB0IiwgIjI4cHQiLCAiMzBwdCIsICIzMnB0IiksCgogIC8vIG5lZWRlZCBmb3IgZWZmaWNpZW50IHJlc2l6aW5nCiAgbGFzdF93aWR0aDogMCwKICBsYXN0X2hlaWdodDogMCwKCgogIC8vIE5lZWRlZCBmb3IgY3Jvc3MgYnJvd3NlciBzdXBwb3J0IGZvciByZWxhdGl2ZSB3aWR0aC9oZWlnaHQgb24KICAvLyBvYmplY3QgZWxlbWVudHMuIFRoZSB3b3JrIGFyb3VuZCBpcyB0byBzYXZlIHdpZHRoL2hlaWdodCBhdHRyaWJ1dGVzCiAgLy8gYW5kIHRoZW4gdG8gcmVjb21wdXRlIGFic29sdXRlIHdpZHRoL2hlaWdodCBkaW1lbnNpb25zIG9uIHJlc2l6aW5nCiAgIG9iamVjdHM6IFtdLAoKICAvLyBhdHRhY2ggaW5pdGlhbGlhdGlvbiBldmVudCBoYW5kbGVycwogIHNldF91cDogZnVuY3Rpb24gKCkgewogICAgdmFyIGluaXQgPSBmdW5jdGlvbigpIHsgdzNjX3NsaWR5LmluaXQoKTsgfTsKICAgIGlmICh0eXBlb2Ygd2luZG93LmFkZEV2ZW50TGlzdGVuZXIgIT0gInVuZGVmaW5lZCIpCiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJsb2FkIiwgaW5pdCwgZmFsc2UpOwogICAgZWxzZQogICAgICB3aW5kb3cuYXR0YWNoRXZlbnQoIm9ubG9hZCIsIGluaXQpOwogIH0sCgogIGhpZGVfc2xpZGVzOiBmdW5jdGlvbiAoKSB7CiAgICBpZiAoZG9jdW1lbnQuYm9keSAmJiAhdzNjX3NsaWR5LmluaXRpYWxpemVkKQogICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnZpc2liaWxpdHkgPSAiaGlkZGVuIjsKICAgIGVsc2UKICAgICAgc2V0VGltZW91dCh3M2Nfc2xpZHkuaGlkZV9zbGlkZXMsIDUwKTsKICB9LAoKICAvLyBoYWNrIHRvIHBlcnN1YWRlIElFIHRvIGNvbXB1dGUgY29ycmVjdCBkb2N1bWVudCBoZWlnaHQKICAvLyBhcyBuZWVkZWQgZm9yIHNpbXVsYXRpbmcgZml4ZWQgcG9zaXRpb25pbmcgb2YgdG9vbGJhcgogIGllX2hhY2s6IGZ1bmN0aW9uICgpIHsKICAgIHdpbmRvdy5yZXNpemVCeSgwLC0xKTsKICAgIHdpbmRvdy5yZXNpemVCeSgwLCAxKTsKICB9LAoKICBpbml0OiBmdW5jdGlvbiAoKSB7CiAgICAvL2FsZXJ0KCJzbGlkeSBzdGFydGluZyB0ZXN0IDEwIik7CiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnZpc2liaWxpdHkgPSAidmlzaWJsZSI7CiAgICB0aGlzLmluaXRfbG9jYWxpemF0aW9uKCk7CiAgICB0aGlzLmFkZF90b29sYmFyKCk7CiAgICB0aGlzLndyYXBfaW1wbGljaXRfc2xpZGVzKCk7CiAgICB0aGlzLmNvbGxlY3Rfc2xpZGVzKCk7CiAgICB0aGlzLmNvbGxlY3Rfbm90ZXMoKTsKICAgIHRoaXMuY29sbGVjdF9iYWNrZ3JvdW5kcygpOwogICAgdGhpcy5vYmplY3RzID0gZG9jdW1lbnQuYm9keS5nZXRFbGVtZW50c0J5VGFnTmFtZSgib2JqZWN0Iik7CiAgICB0aGlzLnBhdGNoX2FuY2hvcnMoKTsKICAgIHRoaXMuc2xpZGVfbnVtYmVyID0gdGhpcy5maW5kX3NsaWRlX251bWJlcihsb2NhdGlvbi5ocmVmKTsKICAgIHdpbmRvdy5vZmZzY3JlZW5idWZmZXJpbmcgPSB0cnVlOwogICAgdGhpcy5zaXplX2FkanVzdG1lbnQgPSB0aGlzLmZpbmRfc2l6ZV9hZGp1c3QoKTsKICAgIHRoaXMudGltZV9sZWZ0ID0gdGhpcy5maW5kX2R1cmF0aW9uKCk7CiAgICB0aGlzLmhpZGVfaW1hZ2VfdG9vbGJhcigpOyAgLy8gc3VwcHJlc3MgSUUgaW1hZ2UgdG9vbGJhciBwb3B1cAogICAgdGhpcy5pbml0X291dGxpbmVyKCk7ICAvLyBhY3RpdmF0ZSBmb2xkL3VuZm9sZCBzdXBwb3J0CiAgICB0aGlzLnRpdGxlID0gZG9jdW1lbnQudGl0bGU7CiAgICB0aGlzLmtleWJvYXJkbGVzcyA9ICh0aGlzLmlwYWR8fHRoaXMuaXBob25lfHx0aGlzLmFuZHJvaWQpOwoKICAgIGlmICh0aGlzLmtleWJvYXJkbGVzcykKICAgIHsKICAgICAgdzNjX3NsaWR5LnJlbW92ZV9jbGFzcyh3M2Nfc2xpZHkudG9vbGJhciwgImhpZGRlbiIpCiAgICAgIHRoaXMud2FudF90b29sYmFyID0gMDsKICAgIH0KCiAgICAvLyB3b3JrIGFyb3VuZCBmb3Igb3BlcmEgYnVnCiAgICB0aGlzLmlzX3hodG1sID0gKGRvY3VtZW50LmJvZHkudGFnTmFtZSA9PSAiQk9EWSIgPyBmYWxzZSA6IHRydWUpOwoKICAgIGlmICh0aGlzLnNsaWRlcy5sZW5ndGggPiAwKQogICAgewogICAgICB2YXIgc2xpZGUgPSB0aGlzLnNsaWRlc1t0aGlzLnNsaWRlX251bWJlcl07CiAgIAogICAgICBpZiAodGhpcy5zbGlkZV9udW1iZXIgPiAwKQogICAgICB7CiAgICAgICAgdGhpcy5zZXRfdmlzaWJpbGl0eV9hbGxfaW5jcmVtZW50YWwoInZpc2libGUiKTsKICAgICAgICB0aGlzLmxhc3Rfc2hvd24gPSB0aGlzLnByZXZpb3VzX2luY3JlbWVudGFsX2l0ZW0obnVsbCk7CiAgICAgICAgdGhpcy5zZXRfZW9zX3N0YXR1cyh0cnVlKTsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICB0aGlzLmxhc3Rfc2hvd24gPSBudWxsOwogICAgICAgIHRoaXMuc2V0X3Zpc2liaWxpdHlfYWxsX2luY3JlbWVudGFsKCJoaWRkZW4iKTsKICAgICAgICB0aGlzLnNldF9lb3Nfc3RhdHVzKCF0aGlzLm5leHRfaW5jcmVtZW50YWxfaXRlbSh0aGlzLmxhc3Rfc2hvd24pKTsKICAgICAgfQoKICAgICAgdGhpcy5zZXRfbG9jYXRpb24oKTsKICAgICAgdGhpcy5hZGRfY2xhc3ModGhpcy5zbGlkZXNbMF0sICJmaXJzdC1zbGlkZSIpOwogICAgICB3M2Nfc2xpZHkuc2hvd19zbGlkZShzbGlkZSk7CiAgICB9CgogICAgdGhpcy50b2MgPSB0aGlzLnRhYmxlX29mX2NvbnRlbnRzKCk7CgogICAgdGhpcy5hZGRfaW5pdGlhbF9wcm9tcHQoKTsKCiAgICAvLyBiaW5kIGV2ZW50IGhhbmRsZXJzIHdpdGhvdXQgaW50ZXJmZXJpbmcgd2l0aCBjdXN0b20gcGFnZSBzY3JpcHRzCiAgICAvLyBUYXAgZXZlbnRzIGJlaGF2ZSB0b28gd2VpcmRseSB0byBzdXBwb3J0IGNsaWNrcyByZWxpYWJseSBvbgogICAgLy8gaVBob25lIGFuZCBpUGFkLCBzbyBleGNsdWRlIHRoZXNlIGZyb20gY2xpY2sgaGFuZGxlcgoKICAgIGlmICghdGhpcy5rZXlib2FyZGxlc3MpCiAgICB7CiAgICAgIHRoaXMuYWRkX2xpc3RlbmVyKGRvY3VtZW50LmJvZHksICJjbGljayIsIHRoaXMubW91c2VfYnV0dG9uX2NsaWNrKTsKICAgICAgdGhpcy5hZGRfbGlzdGVuZXIoZG9jdW1lbnQuYm9keSwgIm1vdXNlZG93biIsIHRoaXMubW91c2VfYnV0dG9uX2Rvd24pOwogICAgfQoKICAgIHRoaXMuYWRkX2xpc3RlbmVyKGRvY3VtZW50LCAia2V5ZG93biIsIHRoaXMua2V5X2Rvd24pOwogICAgdGhpcy5hZGRfbGlzdGVuZXIoZG9jdW1lbnQsICJrZXlwcmVzcyIsIHRoaXMua2V5X3ByZXNzKTsKICAgIHRoaXMuYWRkX2xpc3RlbmVyKHdpbmRvdywgInJlc2l6ZSIsIHRoaXMucmVzaXplZCk7CiAgICB0aGlzLmFkZF9saXN0ZW5lcih3aW5kb3csICJzY3JvbGwiLCB0aGlzLnNjcm9sbGVkKTsKICAgIHRoaXMuYWRkX2xpc3RlbmVyKHdpbmRvdywgInVubG9hZCIsIHRoaXMudW5sb2FkZWQpOwoKICAgIHRoaXMuYWRkX2xpc3RlbmVyKGRvY3VtZW50LCAiZ2VzdHVyZWNoYW5nZSIsIGZ1bmN0aW9uICgpCiAgICB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0pOwoKICAgIHRoaXMuYXR0YWNoX3RvdWNoX2hhbmRlcnModGhpcy5zbGlkZXMpOwoKICAgIC8vIHRoaXMgc2VlbXMgdG8gYmUgYSBkZWJ1Z2dpbmcgaGFjawogICAgLy9pZiAoIWRvY3VtZW50LmJvZHkub25jbGljaykKICAgIC8vICBkb2N1bWVudC5ib2R5Lm9uY2xpY2sgPSBmdW5jdGlvbiAoKSB7IH07CgogICAgdGhpcy5zaW5nbGVfc2xpZGVfdmlldygpOwoKICAgIC8vdGhpcy5zZXRfbG9jYXRpb24oKTsKCiAgICB0aGlzLnJlc2l6ZWQoKTsKCiAgICBpZiAodGhpcy5pZTcpCiAgICAgIHNldFRpbWVvdXQodzNjX3NsaWR5LmllX2hhY2ssIDEwMCk7CgogICAgdGhpcy5zaG93X3Rvb2xiYXIoKTsKCiAgICAvLyBmb3IgYmFjayBidXR0b24gZGV0ZWN0aW9uCiAgICBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7IHczY19zbGlkeS5jaGVja19sb2NhdGlvbigpOyB9LCAyMDApOwogICAgdzNjX3NsaWR5LmluaXRpYWxpemVkID0gdHJ1ZTsKICB9LAoKICAvLyBjcmVhdGUgZGl2IGVsZW1lbnQgd2l0aCBsaW5rcyB0byBlYWNoIHNsaWRlCiAgdGFibGVfb2ZfY29udGVudHM6IGZ1bmN0aW9uICgpIHsKICAgIHZhciB0b2MgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJkaXYiKTsKICAgIHRoaXMuYWRkX2NsYXNzKHRvYywgInNsaWR5X3RvYyBoaWRkZW4iKTsKICAgIC8vdG9jLnNldEF0dHJpYnV0ZSgidGFiaW5kZXgiLCAiMCIpOwoKICAgIHZhciBoZWFkaW5nID0gdGhpcy5jcmVhdGVfZWxlbWVudCgiZGl2Iik7CiAgICB0aGlzLmFkZF9jbGFzcyhoZWFkaW5nLCAidG9jLWhlYWRpbmciKTsKICAgIGhlYWRpbmcuaW5uZXJIVE1MID0gdGhpcy5sb2NhbGl6ZSgiVGFibGUgb2YgQ29udGVudHMiKTsKCiAgICB0b2MuYXBwZW5kQ2hpbGQoaGVhZGluZyk7CiAgICB2YXIgcHJldmlvdXMgPSBudWxsOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5zbGlkZXMubGVuZ3RoOyArK2kpCiAgICB7CiAgICAgIHZhciB0aXRsZSA9IHRoaXMuaGFzX2NsYXNzKHRoaXMuc2xpZGVzW2ldLCAidGl0bGUiKTsKICAgICAgdmFyIG51bSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKChpICsgMSkgKyAiLiAiKTsKCiAgICAgIHRvYy5hcHBlbmRDaGlsZChudW0pOwoKICAgICAgdmFyIGEgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJhIik7CiAgICAgIGEuc2V0QXR0cmlidXRlKCJocmVmIiwgIiMoIiArIChpKzEpICsgIikiKTsKCiAgICAgIGlmICh0aXRsZSkKICAgICAgICB0aGlzLmFkZF9jbGFzcyhhLCAidGl0bGVzbGlkZSIpOwoKICAgICAgdmFyIG5hbWUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0aGlzLnNsaWRlX25hbWUoaSkpOwogICAgICBhLmFwcGVuZENoaWxkKG5hbWUpOwogICAgICBhLm9uY2xpY2sgPSB3M2Nfc2xpZHkudG9jX2NsaWNrOwogICAgICBhLm9ua2V5ZG93biA9IHczY19zbGlkeS50b2Nfa2V5X2Rvd247CiAgICAgIGEucHJldmlvdXMgPSBwcmV2aW91czsKCiAgICAgIGlmIChwcmV2aW91cykKICAgICAgICBwcmV2aW91cy5uZXh0ID0gYTsKCiAgICAgIHRvYy5hcHBlbmRDaGlsZChhKTsKCiAgICAgIGlmIChpID09IDApCiAgICAgICAgdG9jLmZpcnN0ID0gYTsKCiAgICAgIGlmIChpIDwgdGhpcy5zbGlkZXMubGVuZ3RoIC0gMSkKICAgICAgewogICAgICAgIHZhciBiciA9IHRoaXMuY3JlYXRlX2VsZW1lbnQoImJyIik7CiAgICAgICAgdG9jLmFwcGVuZENoaWxkKGJyKTsKICAgICAgfQoKICAgICAgcHJldmlvdXMgPSBhOwogICAgfQoKICAgIHRvYy5mb2N1cyA9IGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKHRoaXMuZmlyc3QpCiAgICAgICAgdGhpcy5maXJzdC5mb2N1cygpOwogICAgfQoKICAgIHRvYy5vbm1vdXNldXAgPSB3M2Nfc2xpZHkubW91c2VfYnV0dG9uX3VwOwoKICAgIHRvYy5vbmNsaWNrID0gZnVuY3Rpb24gKGUpIHsKICAgICAgZXx8KGU9d2luZG93LmV2ZW50KTsKCiAgICAgIGlmICh3M2Nfc2xpZHkuc2VsZWN0ZWRfdGV4dF9sZW4gPD0gMCkKICAgICAgICAgdzNjX3NsaWR5LmhpZGVfdGFibGVfb2ZfY29udGVudHModHJ1ZSk7CgogICAgICB3M2Nfc2xpZHkuc3RvcF9wcm9wYWdhdGlvbihlKTsKICAgIAogICAgICBpZiAoZS5jYW5jZWwgIT0gdW5kZWZpbmVkKQogICAgICAgIGUuY2FuY2VsID0gdHJ1ZTsKICAgICAgCiAgICAgIGlmIChlLnJldHVyblZhbHVlICE9IHVuZGVmaW5lZCkKICAgICAgICBlLnJldHVyblZhbHVlID0gZmFsc2U7CiAgICAgIAogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIGRvY3VtZW50LmJvZHkuaW5zZXJ0QmVmb3JlKHRvYywgZG9jdW1lbnQuYm9keS5maXJzdENoaWxkKTsKICAgIHJldHVybiB0b2M7CiAgfSwKCiAgaXNfc2hvd25fdG9jOiBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gIXczY19zbGlkeS5oYXNfY2xhc3ModzNjX3NsaWR5LnRvYywgImhpZGRlbiIpOwogIH0sCgogIHNob3dfdGFibGVfb2ZfY29udGVudHM6IGZ1bmN0aW9uICgpIHsKICAgIHczY19zbGlkeS5yZW1vdmVfY2xhc3ModzNjX3NsaWR5LnRvYywgImhpZGRlbiIpOwogICAgdmFyIHRvYyA9IHczY19zbGlkeS50b2M7CiAgICB0b2MuZm9jdXMoKTsKCiAgICBpZiAodzNjX3NsaWR5LmllNyAmJiB3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyID09IDApCiAgICAgIHNldFRpbWVvdXQodzNjX3NsaWR5LmllX2hhY2ssIDEwMCk7CiAgfSwKCiAgaGlkZV90YWJsZV9vZl9jb250ZW50czogZnVuY3Rpb24gKGZvY3VzKSB7CiAgICB3M2Nfc2xpZHkuYWRkX2NsYXNzKHczY19zbGlkeS50b2MsICJoaWRkZW4iKTsKCiAgICBpZiAoZm9jdXMgJiYgIXczY19zbGlkeS5vcGVyYSAmJgogICAgICAgICF3M2Nfc2xpZHkuaGFzX2NsYXNzKHczY19zbGlkeS50b2MsICJoaWRkZW4iKSkKICAgICAgdzNjX3NsaWR5LnNldF9mb2N1cygpOwogIH0sCgogIHRvZ2dsZV90YWJsZV9vZl9jb250ZW50czogZnVuY3Rpb24gKCkgewogICAgaWYgKHczY19zbGlkeS5pc19zaG93bl90b2MoKSkKICAgICAgdzNjX3NsaWR5LmhpZGVfdGFibGVfb2ZfY29udGVudHModHJ1ZSk7CiAgICBlbHNlCiAgICAgIHczY19zbGlkeS5zaG93X3RhYmxlX29mX2NvbnRlbnRzKCk7CiAgfSwKCiAgLy8gY2FsbGVkIG9uIGNsaWNraW5nIHRvYyBlbnRyeQogIHRvY19jbGljazogZnVuY3Rpb24gKGUpIHsKICAgIGlmICghZSkKICAgICAgZSA9IHdpbmRvdy5ldmVudDsKCiAgICB2YXIgdGFyZ2V0ID0gdzNjX3NsaWR5LmdldF90YXJnZXQoZSk7CgogICAgaWYgKHRhcmdldCAmJiB0YXJnZXQubm9kZVR5cGUgPT0gMSkKICAgIHsKICAgICAgdmFyIHVyaSA9IHRhcmdldC5nZXRBdHRyaWJ1dGUoImhyZWYiKTsKCiAgICAgIGlmICh1cmkpCiAgICAgIHsKICAgICAgICAvL2FsZXJ0KCJnb2luZyB0byAiICsgdXJpKTsKICAgICAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgICAgIHczY19zbGlkeS5oaWRlX3NsaWRlKHNsaWRlKTsKICAgICAgICB3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyID0gdzNjX3NsaWR5LmZpbmRfc2xpZGVfbnVtYmVyKHVyaSk7CiAgICAgICAgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgICAgIHczY19zbGlkeS5sYXN0X3Nob3duID0gbnVsbDsKICAgICAgICB3M2Nfc2xpZHkuc2V0X2xvY2F0aW9uKCk7CiAgICAgICAgdzNjX3NsaWR5LnNldF92aXNpYmlsaXR5X2FsbF9pbmNyZW1lbnRhbCgiaGlkZGVuIik7CiAgICAgICAgdzNjX3NsaWR5LnNldF9lb3Nfc3RhdHVzKCF3M2Nfc2xpZHkubmV4dF9pbmNyZW1lbnRhbF9pdGVtKHczY19zbGlkeS5sYXN0X3Nob3duKSk7CiAgICAgICAgdzNjX3NsaWR5LnNob3dfc2xpZGUoc2xpZGUpOwogICAgICAgIC8vdGFyZ2V0LmZvY3VzKCk7CgogICAgICAgIHRyeQogICAgICAgIHsKICAgICAgICAgIGlmICghdzNjX3NsaWR5Lm9wZXJhKQogICAgICAgICAgICB3M2Nfc2xpZHkuc2V0X2ZvY3VzKCk7CiAgICAgICAgfQogICAgICAgIGNhdGNoIChlKQogICAgICAgIHsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICB3M2Nfc2xpZHkuaGlkZV90YWJsZV9vZl9jb250ZW50cyh0cnVlKTsKICAgIGlmICh3M2Nfc2xpZHkuaWU3KSB3M2Nfc2xpZHkuaWVfaGFjaygpOwogICAgdzNjX3NsaWR5LnN0b3BfcHJvcGFnYXRpb24oZSk7CiAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChlKTsKICB9LAoKICAvLyBjYWxsZWQgb25rZXlkb3duIGZvciB0b2MgZW50cnkKICB0b2Nfa2V5X2Rvd246IGZ1bmN0aW9uIChldmVudCkgewogICAgdmFyIGtleTsKCiAgICBpZiAoIWV2ZW50KQogICAgICB2YXIgZXZlbnQgPSB3aW5kb3cuZXZlbnQ7CgogICAgLy8ga2x1ZGdlIGFyb3VuZCBOUy9JRSBkaWZmZXJlbmNlcyAKICAgIGlmICh3aW5kb3cuZXZlbnQpCiAgICAgIGtleSA9IHdpbmRvdy5ldmVudC5rZXlDb2RlOwogICAgZWxzZSBpZiAoZXZlbnQud2hpY2gpCiAgICAgIGtleSA9IGV2ZW50LndoaWNoOwogICAgZWxzZQogICAgICByZXR1cm4gdHJ1ZTsgLy8gWWlrZXMhIHVua25vd24gYnJvd3NlcgoKICAgIC8vIGlnbm9yZSBldmVudCBpZiBrZXkgdmFsdWUgaXMgemVybwogICAgLy8gYXMgZm9yIGFsdCBvbiBPcGVyYSBhbmQgS29ucXVlcm9yCiAgICBpZiAoIWtleSkKICAgICAgcmV0dXJuIHRydWU7CgogICAgLy8gY2hlY2sgZm9yIGNvbmN1cnJlbnQgY29udHJvbC9jb21tYW5kL2FsdCBrZXkKICAgIC8vIGJ1dCBhcmUgdGhlc2Ugb25seSBwcmVzZW50IG9uIG1vdXNlIGV2ZW50cz8KCiAgICBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5hbHRLZXkpCiAgICAgIHJldHVybiB0cnVlOwoKICAgIGlmIChrZXkgPT0gMTMpCiAgICB7CiAgICAgIHZhciB1cmkgPSB0aGlzLmdldEF0dHJpYnV0ZSgiaHJlZiIpOwoKICAgICAgaWYgKHVyaSkKICAgICAgewogICAgICAgIC8vYWxlcnQoImdvaW5nIHRvICIgKyB1cmkpOwogICAgICAgdmFyIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICB3M2Nfc2xpZHkuaGlkZV9zbGlkZShzbGlkZSk7CiAgICAgICAgdzNjX3NsaWR5LnNsaWRlX251bWJlciA9IHczY19zbGlkeS5maW5kX3NsaWRlX251bWJlcih1cmkpOwogICAgICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICB3M2Nfc2xpZHkubGFzdF9zaG93biA9IG51bGw7CiAgICAgICAgdzNjX3NsaWR5LnNldF9sb2NhdGlvbigpOwogICAgICAgIHczY19zbGlkeS5zZXRfdmlzaWJpbGl0eV9hbGxfaW5jcmVtZW50YWwoImhpZGRlbiIpOwogICAgICAgIHczY19zbGlkeS5zZXRfZW9zX3N0YXR1cyghdzNjX3NsaWR5Lm5leHRfaW5jcmVtZW50YWxfaXRlbSh3M2Nfc2xpZHkubGFzdF9zaG93bikpOwogICAgICAgIHczY19zbGlkeS5zaG93X3NsaWRlKHNsaWRlKTsKICAgICAgICAvL3RhcmdldC5mb2N1cygpOwoKICAgICAgICB0cnkKICAgICAgICB7CiAgICAgICAgICBpZiAoIXczY19zbGlkeS5vcGVyYSkKICAgICAgICAgICAgdzNjX3NsaWR5LnNldF9mb2N1cygpOwogICAgICAgIH0KICAgICAgICBjYXRjaCAoZSkKICAgICAgICB7CiAgICAgICAgfQogICAgICB9CgogICAgICB3M2Nfc2xpZHkuaGlkZV90YWJsZV9vZl9jb250ZW50cyh0cnVlKTsKCiAgICAgIGlmIChzZWxmLmllNykKICAgICAgIHczY19zbGlkeS5pZV9oYWNrKCk7CgogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CgogICAgaWYgKGtleSA9PSA0MCAmJiB0aGlzLm5leHQpCiAgICB7CiAgICAgIHRoaXMubmV4dC5mb2N1cygpOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CgogICAgaWYgKGtleSA9PSAzOCAmJiB0aGlzLnByZXZpb3VzKQogICAgewogICAgICB0aGlzLnByZXZpb3VzLmZvY3VzKCk7CiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9LAoKICB0b3VjaHN0YXJ0OiBmdW5jdGlvbiAoZSkKICB7CiAgICAvLyBhIGRvdWJsZSB0b3VjaCBvZnRlbiBzdGFydHMgd2l0aCBhCiAgICAvLyBzaW5nbGUgdG91Y2ggZHVlIHRvIGZpbmdlcnMgdG91Y2hpbmcKICAgIC8vIGRvd24gYXQgc2xpZ2h0bHkgZGlmZmVyZW50IHRpbWVzCiAgICAvLyB0aHVzIGF2b2lkIGNhbGxpbmcgcHJldmVudERlZmF1bHQgaGVyZQogICAgdGhpcy5wcmV2X3RhcCA9IHRoaXMubGFzdF90YXA7CiAgICB0aGlzLmxhc3RfdGFwID0gKG5ldyBEYXRlKS5nZXRUaW1lKCk7CgogICAgdmFyIHRhcF9kZWxheSA9IHRoaXMubGFzdF90YXAgLSB0aGlzLnByZXZfdGFwOwoKICAgIGlmICh0YXBfZGVsYXkgPD0gMjAwKQogICAgewogICAgICAvLyBkb3VibGUgdGFwCiAgICB9CgogICAgdmFyIHRvdWNoID0gZS50b3VjaGVzWzBdOwoKICAgIHRoaXMucGFnZVggPSB0b3VjaC5wYWdlWDsKICAgIHRoaXMucGFnZVkgPSB0b3VjaC5wYWdlWTsKICAgIHRoaXMuc2NyZWVuWCA9IHRvdWNoLnNjcmVlblg7CiAgICB0aGlzLnNjcmVlblkgPSB0b3VjaC5zY3JlZW5ZOwogICAgdGhpcy5jbGllbnRYID0gdG91Y2guY2xpZW50WDsKICAgIHRoaXMuY2xpZW50WSA9IHRvdWNoLmNsaWVudFk7CgogICAgdGhpcy5kZWx0YV94ID0gdGhpcy5kZWx0YV95ID0gMDsKICB9LAoKICB0b3VjaG1vdmU6IGZ1bmN0aW9uIChlKQogIHsKICAgIC8vIG92ZXJyaWRlIG5hdGl2ZSBnZXN0dXJlcyBmb3Igc2luZ2xlIHRvdWNoCiAgICBpZiAoZS50b3VjaGVzLmxlbmd0aCA+IDEpCiAgICAgIHJldHVybjsKCiAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICB2YXIgdG91Y2ggPSBlLnRvdWNoZXNbMF07CiAgICB0aGlzLmRlbHRhX3ggPSB0b3VjaC5wYWdlWCAtIHRoaXMucGFnZVg7CiAgICB0aGlzLmRlbHRhX3kgPSB0b3VjaC5wYWdlWSAtIHRoaXMucGFnZVk7CiAgfSwKCiAgdG91Y2hlbmQ6IGZ1bmN0aW9uIChlKQogIHsKICAgIC8vIGRlZmF1bHQgYmVoYXZpb3IgZm9yIG11bHRpLXRvdWNoCiAgICBpZiAoZS50b3VjaGVzLmxlbmd0aCA+IDEpCiAgICAgIHJldHVybjsKCiAgICB2YXIgZGVsYXkgPSAobmV3IERhdGUpLmdldFRpbWUoKSAtIHRoaXMubGFzdF90YXA7CiAgICB2YXIgZHggPSB0aGlzLmRlbHRhX3g7CiAgICB2YXIgZHkgPSB0aGlzLmRlbHRhX3k7CiAgICB2YXIgYWJzX2R4ID0gTWF0aC5hYnMoZHgpOwogICAgdmFyIGFic19keSA9IE1hdGguYWJzKGR5KTsKCiAgICBpZiAoZGVsYXkgPCA1MDAgJiYgKGFic19keCA+IDEwMCB8fCBhYnNfZHkgPiAxMDApKQogICAgewogICAgICBpZiAoYWJzX2R4ID4gMC41ICogYWJzX2R5KQogICAgICB7CiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwoKICAgICAgICBpZiAoZHggPCAwKQogICAgICAgICAgdzNjX3NsaWR5Lm5leHRfc2xpZGUodHJ1ZSk7CiAgICAgICAgZWxzZQogICAgICAgICAgdzNjX3NsaWR5LnByZXZpb3VzX3NsaWRlKHRydWUpOwogICAgICB9CiAgICAgIGVsc2UgaWYgKGFic19keSA+IDIgKiBhYnNfZHgpCiAgICAgIHsKICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgdzNjX3NsaWR5LnRvZ2dsZV90YWJsZV9vZl9jb250ZW50cygpOwogICAgICB9CiAgICB9CiAgfSwKCiAgLy8gIyMjIE9CU09MRVRFICMjIwogIGJlZm9yZV9wcmludDogZnVuY3Rpb24gKCkgewogICAgdGhpcy5zaG93X2FsbF9zbGlkZXMoKTsKICAgIHRoaXMuaGlkZV90b29sYmFyKCk7CiAgICBhbGVydCgiYmVmb3JlIHByaW50Iik7CiAgfSwKCiAgLy8gIyMjIE9CU09MRVRFICMjIwogIGFmdGVyX3ByaW50OiBmdW5jdGlvbiAoKSB7CiAgICBpZiAoIXRoaXMudmlld19hbGwpCiAgICB7CiAgICAgIHRoaXMuc2luZ2xlX3NsaWRlX3ZpZXcoKTsKICAgICAgdGhpcy5zaG93X3Rvb2xiYXIoKTsKICAgIH0KICAgIGFsZXJ0KCJhZnRlciBwcmludCIpOwogIH0sCgogIC8vICMjIyBPQlNPTEVURSAjIyMKICBwcmludF9zbGlkZXM6IGZ1bmN0aW9uICgpIHsKICAgIHRoaXMuYmVmb3JlX3ByaW50KCk7CiAgICB3aW5kb3cucHJpbnQoKTsKICAgIHRoaXMuYWZ0ZXJfcHJpbnQoKTsKICB9LAoKICAvLyAjIyMgT0JTT0xFVEUgPz8gIyMjCiAgdG9nZ2xlX3ZpZXc6IGZ1bmN0aW9uICgpIHsKICAgIGlmICh0aGlzLnZpZXdfYWxsKQogICAgewogICAgICB0aGlzLnNpbmdsZV9zbGlkZV92aWV3KCk7CiAgICAgIHRoaXMuc2hvd190b29sYmFyKCk7CiAgICAgIHRoaXMudmlld19hbGwgPSAwOwogICAgfQogICAgZWxzZQogICAgewogICAgICB0aGlzLnNob3dfYWxsX3NsaWRlcygpOwogICAgICB0aGlzLmhpZGVfdG9vbGJhcigpOwogICAgICB0aGlzLnZpZXdfYWxsID0gMTsKICAgIH0KICB9LAoKICAvLyBwcmVwYXJlIGZvciBwcmludGluZyAgIyMjIE9CU09MRVRFICMjIwogIHNob3dfYWxsX3NsaWRlczogZnVuY3Rpb24gKCkgewogICAgdGhpcy5yZW1vdmVfY2xhc3MoZG9jdW1lbnQuYm9keSwgInNpbmdsZV9zbGlkZSIpOwogICAgdGhpcy5zZXRfdmlzaWJpbGl0eV9hbGxfaW5jcmVtZW50YWwoInZpc2libGUiKTsKICB9LAoKICAvLyByZXN0b3JlIGFmdGVyIHByaW50aW5nICAjIyMgT0JTT0xFVEUgIyMjCiAgc2luZ2xlX3NsaWRlX3ZpZXc6IGZ1bmN0aW9uICgpIHsKICAgIHRoaXMuYWRkX2NsYXNzKGRvY3VtZW50LmJvZHksICJzaW5nbGVfc2xpZGUiKTsKICAgIHRoaXMuc2V0X3Zpc2liaWxpdHlfYWxsX2luY3JlbWVudGFsKCJ2aXNpYmxlIik7CiAgICB0aGlzLmxhc3Rfc2hvd24gPSB0aGlzLnByZXZpb3VzX2luY3JlbWVudGFsX2l0ZW0obnVsbCk7CiAgfSwKCiAgLy8gc3VwcHJlc3MgSUUncyBpbWFnZSB0b29sYmFyIHBvcCB1cAogIGhpZGVfaW1hZ2VfdG9vbGJhcjogZnVuY3Rpb24gKCkgewogICAgaWYgKCF0aGlzLm5zX3BvcykKICAgIHsKICAgICAgdmFyIGltYWdlcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJJTUciKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW1hZ2VzLmxlbmd0aDsgKytpKQogICAgICAgIGltYWdlc1tpXS5zZXRBdHRyaWJ1dGUoImdhbGxlcnlpbWciLCAibm8iKTsKICAgIH0KICB9LAoKICB1bmxvYWRlZDogZnVuY3Rpb24gKGUpIHsKICAgIC8vYWxlcnQoInVubG9hZGVkIik7CiAgfSwKCiAgLy8gU2FmYXJpIGFuZCBLb25xdWVyb3IgZG9uJ3QgeWV0IHN1cHBvcnQgZ2V0Q29tcHV0ZWRTdHlsZSgpCiAgLy8gYW5kIHRoZXkgYWx3YXlzIHJlbG9hZCBwYWdlIHdoZW4gbG9jYXRpb24uaHJlZiBpcyB1cGRhdGVkCiAgaXNfS0hUTUw6IGZ1bmN0aW9uICgpIHsKICAgIHZhciBhZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7CiAgICByZXR1cm4gKGFnZW50LmluZGV4T2YoIktIVE1MIikgPj0gMCA/IHRydWUgOiBmYWxzZSk7CiAgfSwKCiAgLy8gZmluZCBzbGlkZSBuYW1lIGZyb20gZmlyc3QgaDEgZWxlbWVudAogIC8vIGRlZmF1bHQgdG8gZG9jdW1lbnQgdGl0bGUgKyBzbGlkZSBudW1iZXIKICBzbGlkZV9uYW1lOiBmdW5jdGlvbiAoaW5kZXgpIHsKICAgIHZhciBuYW1lID0gbnVsbDsKICAgIHZhciBzbGlkZSA9IHRoaXMuc2xpZGVzW2luZGV4XTsKCiAgICB2YXIgaGVhZGluZyA9IHRoaXMuZmluZF9oZWFkaW5nKHNsaWRlKTsKCiAgICBpZiAoaGVhZGluZykKICAgICAgbmFtZSA9IHRoaXMuZXh0cmFjdF90ZXh0KGhlYWRpbmcpOwoKICAgIGlmICghbmFtZSkKICAgICAgbmFtZSA9IHRoaXMudGl0bGUgKyAiKCIgKyAoaW5kZXggKyAxKSArICIpIjsKCiAgICBuYW1lLnJlcGxhY2UoL1wmL2csICImYW1wOyIpOwogICAgbmFtZS5yZXBsYWNlKC9cPC9nLCAiJmx0OyIpOwogICAgbmFtZS5yZXBsYWNlKC9cPi9nLCAiJmd0OyIpOwoKICAgIHJldHVybiBuYW1lOwogIH0sCgogIC8vIGZpbmQgZmlyc3QgaDEgZWxlbWVudCBpbiBET00gdHJlZQogIGZpbmRfaGVhZGluZzogZnVuY3Rpb24gKG5vZGUpIHsKICAgIGlmICghbm9kZSB8fCBub2RlLm5vZGVUeXBlICE9IDEpCiAgICAgIHJldHVybiBudWxsOwoKICAgIGlmIChub2RlLm5vZGVOYW1lID09ICJIMSIgfHwgbm9kZS5ub2RlTmFtZSA9PSAiaDEiKQogICAgICByZXR1cm4gbm9kZTsKCiAgICB2YXIgY2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7CgogICAgd2hpbGUgKGNoaWxkKQogICAgewogICAgICBub2RlID0gdGhpcy5maW5kX2hlYWRpbmcoY2hpbGQpOwoKICAgICAgaWYgKG5vZGUpCiAgICAgICAgcmV0dXJuIG5vZGU7CgogICAgICBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nOwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0sCgogIC8vIHJlY3Vyc2l2ZWx5IGV4dHJhY3QgdGV4dCBmcm9tIERPTSB0cmVlCiAgZXh0cmFjdF90ZXh0OiBmdW5jdGlvbiAobm9kZSkgewogICAgaWYgKCFub2RlKQogICAgICByZXR1cm4gIiI7CgogICAgLy8gdGV4dCBub2RlcwogICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gMykKICAgICAgcmV0dXJuIG5vZGUubm9kZVZhbHVlOwoKICAgIC8vIGVsZW1lbnRzCiAgICBpZiAobm9kZS5ub2RlVHlwZSA9PSAxKQogICAgewogICAgICBub2RlID0gbm9kZS5maXJzdENoaWxkOwogICAgICB2YXIgdGV4dCA9ICIiOwoKICAgICAgd2hpbGUgKG5vZGUpCiAgICAgIHsKICAgICAgICB0ZXh0ID0gdGV4dCArIHRoaXMuZXh0cmFjdF90ZXh0KG5vZGUpOwogICAgICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nOwogICAgICB9CgogICAgICByZXR1cm4gdGV4dDsKICAgIH0KCiAgICByZXR1cm4gIiI7CiAgfSwKCiAgLy8gZmluZCBjb3B5cmlnaHQgdGV4dCBmcm9tIG1ldGEgZWxlbWVudAogIGZpbmRfY29weXJpZ2h0OiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgbmFtZSwgY29udGVudDsKICAgIHZhciBtZXRhID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIm1ldGEiKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1ldGEubGVuZ3RoOyArK2kpCiAgICB7CiAgICAgIG5hbWUgPSBtZXRhW2ldLmdldEF0dHJpYnV0ZSgibmFtZSIpOwogICAgICBjb250ZW50ID0gbWV0YVtpXS5nZXRBdHRyaWJ1dGUoImNvbnRlbnQiKTsKCiAgICAgIGlmIChuYW1lID09ICJjb3B5cmlnaHQiKQogICAgICAgIHJldHVybiBjb250ZW50OwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0sCgogIGZpbmRfc2l6ZV9hZGp1c3Q6IGZ1bmN0aW9uICgpIHsKICAgIHZhciBuYW1lLCBjb250ZW50LCBvZmZzZXQ7CiAgICB2YXIgbWV0YSA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJtZXRhIik7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXRhLmxlbmd0aDsgKytpKQogICAgewogICAgICBuYW1lID0gbWV0YVtpXS5nZXRBdHRyaWJ1dGUoIm5hbWUiKTsKICAgICAgY29udGVudCA9IG1ldGFbaV0uZ2V0QXR0cmlidXRlKCJjb250ZW50Iik7CgogICAgICBpZiAobmFtZSA9PSAiZm9udC1zaXplLWFkanVzdG1lbnQiKQogICAgICAgIHJldHVybiAxICogY29udGVudDsKICAgIH0KCiAgICByZXR1cm4gMTsKICB9LAoKICAvLyA8bWV0YSBuYW1lPSJkdXJhdGlvbiIgY29udGVudD0iMjAiIC8+ICBmb3IgMjAgbWludXRlcwogIGZpbmRfZHVyYXRpb246IGZ1bmN0aW9uICgpIHsKICAgIHZhciBuYW1lLCBjb250ZW50LCBvZmZzZXQ7CiAgICB2YXIgbWV0YSA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJtZXRhIik7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXRhLmxlbmd0aDsgKytpKQogICAgewogICAgICBuYW1lID0gbWV0YVtpXS5nZXRBdHRyaWJ1dGUoIm5hbWUiKTsKICAgICAgY29udGVudCA9IG1ldGFbaV0uZ2V0QXR0cmlidXRlKCJjb250ZW50Iik7CgogICAgICBpZiAobmFtZSA9PSAiZHVyYXRpb24iKQogICAgICAgIHJldHVybiA2MDAwMCAqIGNvbnRlbnQ7CiAgICB9CgogICAgcmV0dXJuIG51bGw7CiAgfSwKCiAgcmVwbGFjZV9ieV9ub25fYnJlYWtpbmdfc3BhY2U6IGZ1bmN0aW9uIChzdHIpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKQogICAgICBzdHJbaV0gPSAxNjA7CiAgfSwKCiAgLy8gIyMjIENIRUNLIE1FICMjIyBpcyB1c2Ugb2YgImxpIiBva2F5IGZvciB0ZXh0L2h0bWw/CiAgLy8gZm9yIFhIVE1MIGRvIHdlIGFsc28gbmVlZCB0byBzcGVjaWZ5IG5hbWVzcGFjZT8KICBpbml0X291dGxpbmVyOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgaXRlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgibGkiKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgKytpKQogICAgewogICAgICB2YXIgdGFyZ2V0ID0gaXRlbXNbaV07CgogICAgICBpZiAoIXRoaXMuaGFzX2NsYXNzKHRhcmdldC5wYXJlbnROb2RlLCAib3V0bGluZSIpKQogICAgICAgIGNvbnRpbnVlOwoKICAgICAgdGFyZ2V0Lm9uY2xpY2sgPSB0aGlzLm91dGxpbmVfY2xpY2s7Ci8qICMjIyBtb3JlIHdvcmsgbmVlZGVkIGZvciBJRTYKICAgICAgaWYgKCF0aGlzLm5zX3BvcykKICAgICAgewogICAgICAgIHRhcmdldC5vbm1vdXNlb3ZlciA9IHRoaXMuaG92ZXJfb3V0bGluZTsKICAgICAgICB0YXJnZXQub25tb3VzZW91dCA9IHRoaXMudW5ob3Zlcl9vdXRsaW5lOwogICAgICB9CiovCiAgICAgIGlmICh0aGlzLmZvbGRhYmxlKHRhcmdldCkpCiAgICAgIHsKICAgICAgICB0YXJnZXQuZm9sZGFibGUgPSB0cnVlOwogICAgICAgIHRhcmdldC5vbmZvY3VzID0gZnVuY3Rpb24gKCkge3czY19zbGlkeS5vdXRsaW5lID0gdGhpczt9OwogICAgICAgIHRhcmdldC5vbmJsdXIgPSBmdW5jdGlvbiAoKSB7dzNjX3NsaWR5Lm91dGxpbmUgPSBudWxsO307CgogICAgICAgIGlmICghdGFyZ2V0LmdldEF0dHJpYnV0ZSgidGFiaW5kZXgiKSkKICAgICAgICAgIHRhcmdldC5zZXRBdHRyaWJ1dGUoInRhYmluZGV4IiwgIjAiKTsKCiAgICAgICAgaWYgKHRoaXMuaGFzX2NsYXNzKHRhcmdldCwgImV4cGFuZCIpKQogICAgICAgICAgdGhpcy51bmZvbGQodGFyZ2V0KTsKICAgICAgICBlbHNlCiAgICAgICAgICB0aGlzLmZvbGQodGFyZ2V0KTsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICB0aGlzLmFkZF9jbGFzcyh0YXJnZXQsICJub2ZvbGQiKTsKICAgICAgICB0YXJnZXQudmlzaWJsZSA9IHRydWU7CiAgICAgICAgdGFyZ2V0LmZvbGRhYmxlID0gZmFsc2U7CiAgICAgIH0KICAgIH0KICB9LAoKICBmb2xkYWJsZTogZnVuY3Rpb24gKGl0ZW0pIHsKICAgIGlmICghaXRlbSB8fCBpdGVtLm5vZGVUeXBlICE9IDEpCiAgICAgIHJldHVybiBmYWxzZTsKCiAgICB2YXIgbm9kZSA9IGl0ZW0uZmlyc3RDaGlsZDsKCiAgICB3aGlsZSAobm9kZSkKICAgIHsKICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gMSAmJiB0aGlzLmlzX2Jsb2NrKG5vZGUpKQogICAgICAgIHJldHVybiB0cnVlOwoKICAgICAgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmc7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0sCgogIC8vICMjIyBDSEVDSyBNRSAjIyMgc3dpdGNoIHRvIGFkZC9yZW1vdmUgImhpZGRlbiIgY2xhc3MKICBmb2xkOiBmdW5jdGlvbiAoaXRlbSkgewogICAgaWYgKGl0ZW0pCiAgICB7CiAgICAgIHRoaXMucmVtb3ZlX2NsYXNzKGl0ZW0sICJ1bmZvbGRlZCIpOwogICAgICB0aGlzLmFkZF9jbGFzcyhpdGVtLCAiZm9sZGVkIik7CiAgICB9CgogICAgdmFyIG5vZGUgPSBpdGVtID8gaXRlbS5maXJzdENoaWxkIDogbnVsbDsKCiAgICB3aGlsZSAobm9kZSkKICAgIHsKICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gMSAmJiB0aGlzLmlzX2Jsb2NrKG5vZGUpKSAvLyBlbGVtZW50CiAgICAgIHsKICAgICAgICAgdzNjX3NsaWR5LmFkZF9jbGFzcyhub2RlLCAiaGlkZGVuIik7CiAgICAgIH0KCiAgICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nOwogICAgfQoKICAgIGl0ZW0udmlzaWJsZSA9IGZhbHNlOwogIH0sCgogIC8vICMjIyBDSEVDSyBNRSAjIyMgc3dpdGNoIHRvIGFkZC9yZW1vdmUgImhpZGRlbiIgY2xhc3MKICB1bmZvbGQ6IGZ1bmN0aW9uIChpdGVtKSB7CiAgICBpZiAoaXRlbSkKICAgIHsKICAgICAgdGhpcy5hZGRfY2xhc3MoaXRlbSwgInVuZm9sZGVkIik7CiAgICAgIHRoaXMucmVtb3ZlX2NsYXNzKGl0ZW0sICJmb2xkZWQiKTsKICAgIH0KCiAgICB2YXIgbm9kZSA9IGl0ZW0gPyBpdGVtLmZpcnN0Q2hpbGQgOiBudWxsOwoKICAgIHdoaWxlIChub2RlKQogICAgewogICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PSAxICYmIHRoaXMuaXNfYmxvY2sobm9kZSkpIC8vIGVsZW1lbnQKICAgICAgewogICAgICAgIHczY19zbGlkeS5yZW1vdmVfY2xhc3Mobm9kZSwgImhpZGRlbiIpOwogICAgICB9CgogICAgICBub2RlID0gbm9kZS5uZXh0U2libGluZzsKICAgIH0KCiAgICBpdGVtLnZpc2libGUgPSB0cnVlOwogIH0sCgogIG91dGxpbmVfY2xpY2s6IGZ1bmN0aW9uIChlKSB7CiAgICBpZiAoIWUpCiAgICAgIGUgPSB3aW5kb3cuZXZlbnQ7CgogICAgdmFyIHJpZ2h0Y2xpY2sgPSBmYWxzZTsKICAgIHZhciB0YXJnZXQgPSB3M2Nfc2xpZHkuZ2V0X3RhcmdldChlKTsKCiAgICB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldC52aXNpYmxlID09IHVuZGVmaW5lZCkKICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnBhcmVudE5vZGU7CgogICAgaWYgKCF0YXJnZXQpCiAgICAgIHJldHVybiB0cnVlOwoKICAgIGlmIChlLndoaWNoKQogICAgICByaWdodGNsaWNrID0gKGUud2hpY2ggPT0gMyk7CiAgICBlbHNlIGlmIChlLmJ1dHRvbikKICAgICAgcmlnaHRjbGljayA9IChlLmJ1dHRvbiA9PSAyKTsKCiAgICBpZiAoIXJpZ2h0Y2xpY2sgJiYgdGFyZ2V0LnZpc2libGUgIT0gdW5kZWZpbmVkKQogICAgewogICAgICBpZiAodGFyZ2V0LmZvbGRhYmxlKQogICAgICB7CiAgICAgICAgaWYgKHRhcmdldC52aXNpYmxlKQogICAgICAgICAgdzNjX3NsaWR5LmZvbGQodGFyZ2V0KTsKICAgICAgICBlbHNlCiAgICAgICAgICB3M2Nfc2xpZHkudW5mb2xkKHRhcmdldCk7CiAgICAgIH0KCiAgICAgIHczY19zbGlkeS5zdG9wX3Byb3BhZ2F0aW9uKGUpOwogICAgICBlLmNhbmNlbCA9IHRydWU7CiAgICAgIGUucmV0dXJuVmFsdWUgPSBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfSwKCiAgYWRkX2luaXRpYWxfcHJvbXB0OiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgcHJvbXB0ID0gdGhpcy5jcmVhdGVfZWxlbWVudCgiZGl2Iik7CiAgICBwcm9tcHQuc2V0QXR0cmlidXRlKCJjbGFzcyIsICJpbml0aWFsX3Byb21wdCIpOwoKICAgIHZhciBwMSA9IHRoaXMuY3JlYXRlX2VsZW1lbnQoInAiKTsKICAgIHByb21wdC5hcHBlbmRDaGlsZChwMSk7CiAgICBwMS5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgImhlbHAiKTsKCiAgICBpZiAodGhpcy5rZXlib2FyZGxlc3MpCiAgICAgIHAxLmlubmVySFRNTCA9ICJzd2lwZSBsZWZ0IHRvIG1vdmUgdG8gbmV4dCBzbGlkZSI7CiAgICBlbHNlCiAgICAgIHAxLmlubmVySFRNTCA9ICJTcGFjZSwgUmlnaHQgQXJyb3cgb3Igc3dpcGUgbGVmdCB0byBtb3ZlIHRvICIgKwogICAgICAgICAgICAgICAgICAgICAibmV4dCBzbGlkZSwgY2xpY2sgaGVscCBiZWxvdyBmb3IgbW9yZSBkZXRhaWxzIjsKCiAgICB0aGlzLmFkZF9saXN0ZW5lcihwcm9tcHQsICJjbGljayIsIGZ1bmN0aW9uIChlKSB7CiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQocHJvbXB0KTsKICAgICAgdzNjX3NsaWR5LnN0b3BfcHJvcGFnYXRpb24oZSk7CiAgICAKICAgICAgaWYgKGUuY2FuY2VsICE9IHVuZGVmaW5lZCkKICAgICAgICBlLmNhbmNlbCA9IHRydWU7CiAgICAgIAogICAgICBpZiAoZS5yZXR1cm5WYWx1ZSAhPSB1bmRlZmluZWQpCiAgICAgICAgZS5yZXR1cm5WYWx1ZSA9IGZhbHNlOwogICAgICAKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfSk7CgogICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChwcm9tcHQpOwogICAgdGhpcy5pbml0aWFsX3Byb21wdCA9IHByb21wdDsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7ZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChwcm9tcHQpO30sIDUwMDApOwogIH0sCgogIGFkZF90b29sYmFyOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgY291bnRlciwgcGFnZTsKCiAgICAgdGhpcy50b29sYmFyID0gdGhpcy5jcmVhdGVfZWxlbWVudCgiZGl2Iik7CiAgICAgdGhpcy50b29sYmFyLnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAidG9vbGJhciIpOwoKICAgICAvLyBhIHJlYXNvbmFibHkgYmVoYXZlZCBicm93c2VyCiAgICAgaWYgKHRoaXMubnNfcG9zIHx8ICF0aGlzLmllNikKICAgICB7CiAgICAgICB2YXIgcmlnaHQgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJkaXYiKTsKICAgICAgIHJpZ2h0LnNldEF0dHJpYnV0ZSgic3R5bGUiLCAiZmxvYXQ6IHJpZ2h0OyB0ZXh0LWFsaWduOiByaWdodCIpOwoKICAgICAgIGNvdW50ZXIgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJzcGFuIikKICAgICAgIGNvdW50ZXIuaW5uZXJIVE1MID0gdGhpcy5sb2NhbGl6ZSgic2xpZGUiKSArICIgbi9tIjsKICAgICAgIHJpZ2h0LmFwcGVuZENoaWxkKGNvdW50ZXIpOwogICAgICAgdGhpcy50b29sYmFyLmFwcGVuZENoaWxkKHJpZ2h0KTsKCiAgICAgICB2YXIgbGVmdCA9IHRoaXMuY3JlYXRlX2VsZW1lbnQoImRpdiIpOwogICAgICAgbGVmdC5zZXRBdHRyaWJ1dGUoInN0eWxlIiwgInRleHQtYWxpZ246IGxlZnQiKTsKCiAgICAgICAvLyBnbG9iYWwgZW5kIG9mIHNsaWRlIGluZGljYXRvcgogICAgICAgdGhpcy5lb3MgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJzcGFuIik7CiAgICAgICB0aGlzLmVvcy5pbm5lckhUTUwgPSAiKiAiOwogICAgICAgbGVmdC5hcHBlbmRDaGlsZCh0aGlzLmVvcyk7CgogICAgICAgdmFyIGhlbHAgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJhIik7CiAgICAgICBoZWxwLnNldEF0dHJpYnV0ZSgiaHJlZiIsIHRoaXMuaGVscF9wYWdlKTsKICAgICAgIGhlbHAuc2V0QXR0cmlidXRlKCJ0aXRsZSIsIHRoaXMubG9jYWxpemUodGhpcy5oZWxwX3RleHQpKTsKICAgICAgIGhlbHAuaW5uZXJIVE1MID0gdGhpcy5sb2NhbGl6ZSgiaGVscD8iKTsKICAgICAgIGxlZnQuYXBwZW5kQ2hpbGQoaGVscCk7CiAgICAgICBoZWxwLnN0eWxlLmRpc3BsYXk9Im5vbmUiOyAKICAgICAgIHRoaXMuaGVscF9hbmNob3IgPSBoZWxwOyAgLy8gc2F2ZSBmb3IgZm9jdXMgaGFjawoKICAgICAgIHZhciBnYXAxID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoIiAiKTsKICAgICAgIGxlZnQuYXBwZW5kQ2hpbGQoZ2FwMSk7CgogICAgICAgdmFyIGNvbnRlbnRzID0gdGhpcy5jcmVhdGVfZWxlbWVudCgiYSIpOwogICAgICAgY29udGVudHMuc2V0QXR0cmlidXRlKCJocmVmIiwgImphdmFzY3JpcHQ6dzNjX3NsaWR5LnRvZ2dsZV90YWJsZV9vZl9jb250ZW50cygpIik7CiAgICAgICBjb250ZW50cy5zZXRBdHRyaWJ1dGUoInRpdGxlIiwgdGhpcy5sb2NhbGl6ZSgidGFibGUgb2YgY29udGVudHMiKSk7CiAgICAgICBjb250ZW50cy5pbm5lckhUTUwgPSB0aGlzLmxvY2FsaXplKCJDb250ZW50cyIpOwogICAgICAgbGVmdC5hcHBlbmRDaGlsZChjb250ZW50cyk7CgogICAgICAgdmFyIGdhcDIgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgiICIpOwogICAgICAgbGVmdC5hcHBlbmRDaGlsZChnYXAyKTsKCiAgICAgICB2YXIgY29weXJpZ2h0ID0gdGhpcy5maW5kX2NvcHlyaWdodCgpOwoKICAgICAgIGlmIChjb3B5cmlnaHQpCiAgICAgICB7CiAgICAgICAgIHZhciBzcGFuID0gdGhpcy5jcmVhdGVfZWxlbWVudCgic3BhbiIpOwogICAgICAgICBzcGFuLmNsYXNzTmFtZSA9ICJjb3B5cmlnaHQiOwogICAgICAgICBzcGFuLmlubmVySFRNTCA9IGNvcHlyaWdodDsKICAgICAgICAgbGVmdC5hcHBlbmRDaGlsZChzcGFuKTsKICAgICAgIH0KCiAgICAgICB0aGlzLnRvb2xiYXIuc2V0QXR0cmlidXRlKCJ0YWJpbmRleCIsICIwIik7CiAgICAgICB0aGlzLnRvb2xiYXIuYXBwZW5kQ2hpbGQobGVmdCk7CiAgICAgfQogICAgIGVsc2UgLy8gSUU2IHNvIG5lZWQgdG8gd29yayBhcm91bmQgaXRzIHBvb3IgQ1NTIHN1cHBvcnQKICAgICB7CiAgICAgICB0aGlzLnRvb2xiYXIuc3R5bGUucG9zaXRpb24gPSAodGhpcy5pZTcgPyAiZml4ZWQiIDogImFic29sdXRlIik7CiAgICAgICB0aGlzLnRvb2xiYXIuc3R5bGUuekluZGV4ID0gIjIwMCI7CiAgICAgICB0aGlzLnRvb2xiYXIuc3R5bGUud2lkdGggPSAiOTkuOSUiOwogICAgICAgdGhpcy50b29sYmFyLnN0eWxlLmhlaWdodCA9ICIxLjJlbSI7CiAgICAgICB0aGlzLnRvb2xiYXIuc3R5bGUudG9wID0gImF1dG8iOwogICAgICAgdGhpcy50b29sYmFyLnN0eWxlLmJvdHRvbSA9ICIwIjsKICAgICAgIHRoaXMudG9vbGJhci5zdHlsZS5sZWZ0ID0gIjAiOwogICAgICAgdGhpcy50b29sYmFyLnN0eWxlLnJpZ2h0ID0gIjAiOwogICAgICAgdGhpcy50b29sYmFyLnN0eWxlLnRleHRBbGlnbiA9ICJsZWZ0IjsKICAgICAgIHRoaXMudG9vbGJhci5zdHlsZS5mb250U2l6ZSA9ICI2MCUiOwogICAgICAgdGhpcy50b29sYmFyLnN0eWxlLmNvbG9yID0gInJlZCI7CiAgICAgICB0aGlzLnRvb2xiYXIuYm9yZGVyV2lkdGggPSAwOwogICAgICAgdGhpcy50b29sYmFyLmNsYXNzTmFtZSA9ICJ0b29sYmFyIjsKICAgICAgIHRoaXMudG9vbGJhci5zdHlsZS5iYWNrZ3JvdW5kID0gInJnYigyNDAsMjQwLDI0MCkiOwoKICAgICAgIC8vIHdvdWxkIGxpa2UgdG8gaGF2ZSBoZWxwIHRleHQgbGVmdCBhbGlnbmVkCiAgICAgICAvLyBhbmQgcGFnZSBjb3VudGVyIHJpZ2h0IGFsaWduZWQsIGZsb2F0aW5nCiAgICAgICAvLyBkaXYncyBkb24ndCB3b3JrLCBzbyBpbnN0ZWFkIHVzZSBuZXN0ZWQKICAgICAgIC8vIGFic29sdXRlbHkgcG9zaXRpb25lZCBkaXYncy4KCiAgICAgICB2YXIgc3AgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJzcGFuIik7CiAgICAgICBzcC5pbm5lckhUTUwgPSAiJm5ic3A7Jm5ic3A7KiZuYnNwOyI7CiAgICAgICB0aGlzLnRvb2xiYXIuYXBwZW5kQ2hpbGQoc3ApOwogICAgICAgdGhpcy5lb3MgPSBzcDsgIC8vIGVuZCBvZiBzbGlkZSBpbmRpY2F0b3IKCiAgICAgICB2YXIgaGVscCA9IHRoaXMuY3JlYXRlX2VsZW1lbnQoImEiKTsKICAgICAgIGhlbHAuc2V0QXR0cmlidXRlKCJocmVmIiwgdGhpcy5oZWxwX3BhZ2UpOwogICAgICAgaGVscC5zZXRBdHRyaWJ1dGUoInRpdGxlIiwgdGhpcy5sb2NhbGl6ZSh0aGlzLmhlbHBfdGV4dCkpOwogICAgICAgaGVscC5pbm5lckhUTUwgPSB0aGlzLmxvY2FsaXplKCJoZWxwPyIpOwogICAgICAgdGhpcy50b29sYmFyLmFwcGVuZENoaWxkKGhlbHApOwogICAgICAgdGhpcy5oZWxwX2FuY2hvciA9IGhlbHA7ICAvLyBzYXZlIGZvciBmb2N1cyBoYWNrCgogICAgICAgdmFyIGdhcDEgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgiICIpOwogICAgICAgdGhpcy50b29sYmFyLmFwcGVuZENoaWxkKGdhcDEpOwoKICAgICAgIHZhciBjb250ZW50cyA9IHRoaXMuY3JlYXRlX2VsZW1lbnQoImEiKTsKICAgICAgIGNvbnRlbnRzLnNldEF0dHJpYnV0ZSgiaHJlZiIsICJqYXZhc2NyaXB0OnRvZ2dsZVRhYmxlT2ZDb250ZW50cygpIik7CiAgICAgICBjb250ZW50cy5zZXRBdHRyaWJ1dGUoInRpdGxlIiwgdGhpcy5sb2NhbGl6ZSgidGFibGUgb2YgY29udGVudHMiLmxvY2FsaXplKSk7CiAgICAgICBjb250ZW50cy5pbm5lckhUTUwgPSB0aGlzLmxvY2FsaXplKCJjb250ZW50cz8iKTsKICAgICAgIHRoaXMudG9vbGJhci5hcHBlbmRDaGlsZChjb250ZW50cyk7CgogICAgICAgdmFyIGdhcDIgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgiICIpOwogICAgICAgdGhpcy50b29sYmFyLmFwcGVuZENoaWxkKGdhcDIpOwoKICAgICAgIHZhciBjb3B5cmlnaHQgPSB0aGlzLmZpbmRfY29weXJpZ2h0KCk7CgogICAgICAgaWYgKGNvcHlyaWdodCkKICAgICAgIHsKICAgICAgICAgdmFyIHNwYW4gPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJzcGFuIik7CiAgICAgICAgIHNwYW4uaW5uZXJIVE1MID0gY29weXJpZ2h0OwogICAgICAgICBzcGFuLnN0eWxlLmNvbG9yID0gImJsYWNrIjsKICAgICAgICAgc3Bhbi5zdHlsZS5tYXJnaW5MZWZ0ID0gIjAuNWVtIjsKICAgICAgICAgdGhpcy50b29sYmFyLmFwcGVuZENoaWxkKHNwYW4pOwogICAgICAgfQoKICAgICAgIGNvdW50ZXIgPSB0aGlzLmNyZWF0ZV9lbGVtZW50KCJkaXYiKQogICAgICAgY291bnRlci5zdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICAgICBjb3VudGVyLnN0eWxlLndpZHRoID0gImF1dG8iOyAvLyIyMCUiOwogICAgICAgY291bnRlci5zdHlsZS5oZWlnaHQgPSAiMS4yZW0iOwogICAgICAgY291bnRlci5zdHlsZS50b3AgPSAiYXV0byI7CiAgICAgICBjb3VudGVyLnN0eWxlLmJvdHRvbSA9IDA7CiAgICAgICBjb3VudGVyLnN0eWxlLnJpZ2h0ID0gIjAiOwogICAgICAgY291bnRlci5zdHlsZS50ZXh0QWxpZ24gPSAicmlnaHQiOwogICAgICAgY291bnRlci5zdHlsZS5jb2xvciA9ICJyZWQiOwogICAgICAgY291bnRlci5zdHlsZS5iYWNrZ3JvdW5kID0gInJnYigyNDAsMjQwLDI0MCkiOwoKICAgICAgIGNvdW50ZXIuaW5uZXJIVE1MID0gdGhpcy5sb2NhbGl6ZSgic2xpZGUiKSArICIgbi9tIjsKICAgICAgIHRoaXMudG9vbGJhci5hcHBlbmRDaGlsZChjb3VudGVyKTsKICAgICB9CgogICAgIC8vIGVuc3VyZSB0aGF0IGNsaWNrIGlzbid0IHBhc3NlZCB0aHJvdWdoIHRvIHRoZSBwYWdlCiAgICAgdGhpcy50b29sYmFyLm9uY2xpY2sgPQogICAgICAgICBmdW5jdGlvbiAoZSkgewogICAgICAgICAgIGlmICghZSkKICAgICAgICAgICAgIGUgPSB3aW5kb3cuZXZlbnQ7CgogICAgICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldDsKCiAgICAgICAgICAgaWYgKCF0YXJnZXQgJiYgZS5zcmNFbGVtZW50KQogICAgICAgICAgICAgdGFyZ2V0ID0gZS5zcmNFbGVtZW50OwoKICAgICAgICAgICAvLyB3b3JrIGFyb3VuZCBTYWZhcmkgYnVnCiAgICAgICAgICAgaWYgKHRhcmdldCAmJiB0YXJnZXQubm9kZVR5cGUgPT0gMykKICAgICAgICAgICAgIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlOwoKICAgICAgICAgICB3M2Nfc2xpZHkuc3RvcF9wcm9wYWdhdGlvbihlKTsKCiAgICAgICAgICAgaWYgKHRhcmdldCAmJiB0YXJnZXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAhPSAiYSIpCiAgICAgICAgICAgICB3M2Nfc2xpZHkubW91c2VfYnV0dG9uX2NsaWNrKGUpOwogICAgICAgICB9OwoKICAgICB0aGlzLnNsaWRlX251bWJlcl9lbGVtZW50ID0gY291bnRlcjsKICAgICB0aGlzLnNldF9lb3Nfc3RhdHVzKGZhbHNlKTsKICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMudG9vbGJhcik7CiAgfSwKCiAgLy8gd3lzaXd5ZyBlZGl0b3JzIG1ha2UgaXQgaGFyZCB0byB1c2UgZGl2IGVsZW1lbnRzCiAgLy8gZS5nLiBhbWF5YSBsb3NlcyB0aGUgZGl2IHdoZW4geW91IGNvcHkgYW5kIHBhc3RlCiAgLy8gdGhpcyBmdW5jdGlvbiB3cmFwcyBkaXYgZWxlbWVudHMgYXJvdW5kIGltcGxpY2l0CiAgLy8gc2xpZGVzIHdoaWNoIHN0YXJ0IHdpdGggYW4gaDEgZWxlbWVudCBhbmQgY29udGludWUKICAvLyB1cCB0byB0aGUgbmV4dCBoZWFkaW5nIG9yIGRpdiBlbGVtZW50CiAgd3JhcF9pbXBsaWNpdF9zbGlkZXM6IGZ1bmN0aW9uICgpIHsKICAgIHZhciBpLCBoZWFkaW5nLCBub2RlLCBuZXh0LCBkaXY7CiAgICB2YXIgaGVhZGluZ3MgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaDEiKTsKCiAgICBpZiAoIWhlYWRpbmdzKQogICAgICByZXR1cm47CgogICAgZm9yIChpID0gMDsgaSA8IGhlYWRpbmdzLmxlbmd0aDsgKytpKQogICAgewogICAgICBoZWFkaW5nID0gaGVhZGluZ3NbaV07CgogICAgICBpZiAoaGVhZGluZy5wYXJlbnROb2RlICE9IGRvY3VtZW50LmJvZHkpCiAgICAgICAgY29udGludWU7CgogICAgICBub2RlID0gaGVhZGluZy5uZXh0U2libGluZzsKCiAgICAgIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICB0aGlzLmFkZF9jbGFzcyhkaXYsICJzbGlkZSIpOwogICAgICBkb2N1bWVudC5ib2R5LnJlcGxhY2VDaGlsZChkaXYsIGhlYWRpbmcpOwogICAgICBkaXYuYXBwZW5kQ2hpbGQoaGVhZGluZyk7CgogICAgICB3aGlsZSAobm9kZSkKICAgICAgewogICAgICAgIGlmIChub2RlLm5vZGVUeXBlID09IDEpIC8vIGFuIGVsZW1lbnQKICAgICAgICB7CiAgICAgICAgICAgaWYgKG5vZGUubm9kZU5hbWUgPT0gIkgxIiB8fCBub2RlLm5vZGVOYW1lID09ICJoMSIpCiAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgaWYgKG5vZGUubm9kZU5hbWUgPT0gIkRJViIgfHwgbm9kZS5ub2RlTmFtZSA9PSAiZGl2IikKICAgICAgICAgICB7CiAgICAgICAgICAgICBpZiAodGhpcy5oYXNfY2xhc3Mobm9kZSwgInNsaWRlIikpCiAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgIGlmICh0aGlzLmhhc19jbGFzcyhub2RlLCAiaGFuZG91dCIpKQogICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBuZXh0ID0gbm9kZS5uZXh0U2libGluZzsKICAgICAgICBub2RlID0gZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChub2RlKTsKICAgICAgICBkaXYuYXBwZW5kQ2hpbGQobm9kZSk7CiAgICAgICAgbm9kZSA9IG5leHQ7CiAgICAgIH0gCiAgICB9CiAgfSwKCiAgYXR0YWNoX3RvdWNoX2hhbmRlcnM6IGZ1bmN0aW9uKHNsaWRlcykKICB7CiAgICB2YXIgaSwgc2xpZGU7CgogICAgZm9yIChpID0gMDsgaSA8IHNsaWRlcy5sZW5ndGg7ICsraSkKICAgIHsKICAgICAgc2xpZGUgPSBzbGlkZXNbaV07CiAgICAgIHRoaXMuYWRkX2xpc3RlbmVyKHNsaWRlLCAidG91Y2hzdGFydCIsIHRoaXMudG91Y2hzdGFydCk7CiAgICAgIHRoaXMuYWRkX2xpc3RlbmVyKHNsaWRlLCAidG91Y2htb3ZlIiwgdGhpcy50b3VjaG1vdmUpOwogICAgICB0aGlzLmFkZF9saXN0ZW5lcihzbGlkZSwgInRvdWNoZW5kIiwgdGhpcy50b3VjaGVuZCk7CiAgICB9CiAgfSwKCi8vIHJldHVybiBuZXcgYXJyYXkgb2YgYWxsIHNsaWRlcwogIGNvbGxlY3Rfc2xpZGVzOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgc2xpZGVzID0gbmV3IEFycmF5KCk7CiAgICB2YXIgZGl2cyA9IGRvY3VtZW50LmJvZHkuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImRpdiIpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGl2cy5sZW5ndGg7ICsraSkKICAgIHsKICAgICAgZGl2ID0gZGl2cy5pdGVtKGkpOwoKICAgICAgaWYgKHRoaXMuaGFzX2NsYXNzKGRpdiwgInNsaWRlIikpCiAgICAgIHsKICAgICAgICAvLyBhZGQgc2xpZGUgdG8gY29sbGVjdGlvbgogICAgICAgIHNsaWRlc1tzbGlkZXMubGVuZ3RoXSA9IGRpdjsKCiAgICAgICAgLy8gaGlkZSBlYWNoIHNsaWRlIGFzIGl0IGlzIGZvdW5kCiAgICAgICAgdGhpcy5hZGRfY2xhc3MoZGl2LCAiaGlkZGVuIik7CgogICAgICAgIC8vIGFkZCBkdW1teSA8YnIvPiBhdCBlbmQgZm9yIHNjcm9sbGluZyBoYWNrCiAgICAgICAgdmFyIG5vZGUxID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYnIiKTsKICAgICAgICBkaXYuYXBwZW5kQ2hpbGQobm9kZTEpOwogICAgICAgIHZhciBub2RlMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImJyIik7CiAgICAgICAgZGl2LmFwcGVuZENoaWxkKG5vZGUyKTsKICAgICAgfQogICAgICBlbHNlIGlmICh0aGlzLmhhc19jbGFzcyhkaXYsICJiYWNrZ3JvdW5kIikpCiAgICAgIHsgIC8vIHdvcmsgYXJvdW5kIGZvciBGaXJlZm94IFNWRyByZWxvYWQgYnVnCiAgICAgICAgLy8gd2hpY2ggb3RoZXJ3aXNlIHJlcGxhY2VzIDFzdCBTVkcgZ3JhcGhpYyB3aXRoIDJuZAogICAgICAgIGRpdi5zdHlsZS5kaXNwbGF5ID0gImJsb2NrIjsKICAgICAgfQogICAgfQoKICAgIHRoaXMuc2xpZGVzID0gc2xpZGVzOwogIH0sCgogIC8vIHJldHVybiBuZXcgYXJyYXkgb2YgYWxsIDxkaXYgY2xhc3M9ImhhbmRvdXQiPgogIGNvbGxlY3Rfbm90ZXM6IGZ1bmN0aW9uICgpIHsKICAgIHZhciBub3RlcyA9IG5ldyBBcnJheSgpOwogICAgdmFyIGRpdnMgPSBkb2N1bWVudC5ib2R5LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJkaXYiKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpdnMubGVuZ3RoOyArK2kpCiAgICB7CiAgICAgIGRpdiA9IGRpdnMuaXRlbShpKTsKCiAgICAgIGlmICh0aGlzLmhhc19jbGFzcyhkaXYsICJoYW5kb3V0IikpCiAgICAgIHsKICAgICAgICAvLyBhZGQgbm90ZSB0byBjb2xsZWN0aW9uCiAgICAgICAgbm90ZXNbbm90ZXMubGVuZ3RoXSA9IGRpdjsKCiAgICAgICAgLy8gYW5kIGhpZGUgaXQKICAgICAgICB0aGlzLmFkZF9jbGFzcyhkaXYsICJoaWRkZW4iKTsKICAgICAgfQogICAgfQoKICAgIHRoaXMubm90ZXMgPSBub3RlczsKICB9LAoKICAvLyByZXR1cm4gbmV3IGFycmF5IG9mIGFsbCA8ZGl2IGNsYXNzPSJiYWNrZ3JvdW5kIj4KICAvLyBpbmNsdWRpbmcgbmFtZWQgYmFja2dyb3VuZHMgZS5nLiBjbGFzcz0iYmFja2dyb3VuZCB0aXRsZXBhZ2UiCiAgY29sbGVjdF9iYWNrZ3JvdW5kczogZnVuY3Rpb24gKCkgewogICAgdmFyIGJhY2tncm91bmRzID0gbmV3IEFycmF5KCk7CiAgICB2YXIgZGl2cyA9IGRvY3VtZW50LmJvZHkuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImRpdiIpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGl2cy5sZW5ndGg7ICsraSkKICAgIHsKICAgICAgZGl2ID0gZGl2cy5pdGVtKGkpOwoKICAgICAgaWYgKHRoaXMuaGFzX2NsYXNzKGRpdiwgImJhY2tncm91bmQiKSkKICAgICAgewogICAgICAgIC8vIGFkZCBiYWNrZ3JvdW5kIHRvIGNvbGxlY3Rpb24KICAgICAgICBiYWNrZ3JvdW5kc1tiYWNrZ3JvdW5kcy5sZW5ndGhdID0gZGl2OwoKICAgICAgICAvLyBhbmQgaGlkZSBpdAogICAgICAgIHRoaXMuYWRkX2NsYXNzKGRpdiwgImhpZGRlbiIpOwogICAgICB9CiAgICB9CgogICAgdGhpcy5iYWNrZ3JvdW5kcyA9IGJhY2tncm91bmRzOwogIH0sCgogIC8vIHNldCBjbGljayBoYW5kbGVycyBvbiBhbGwgYW5jaG9ycwogIHBhdGNoX2FuY2hvcnM6IGZ1bmN0aW9uICgpIHsKICAgIHZhciBzZWxmID0gdzNjX3NsaWR5OwogICAgdmFyIGhhbmRsZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHsKICAgICAgLy8gY29tcGFyZSB0aGlzLmhyZWYgd2l0aCBsb2NhdGlvbi5ocmVmCiAgICAgIC8vIGZvciBsaW5rIHRvIGFub3RoZXIgc2xpZGUgaW4gdGhpcyBkb2MKCiAgICAgIGlmIChzZWxmLnBhZ2VfYWRkcmVzcyh0aGlzLmhyZWYpID09IHNlbGYucGFnZV9hZGRyZXNzKGxvY2F0aW9uLmhyZWYpKQogICAgICB7CiAgICAgICAgLy8geWVzLCBzbyBmaW5kIG5ldyBzbGlkZSBudW1iZXIKICAgICAgICB2YXIgbmV3c2xpZGVudW0gPSBzZWxmLmZpbmRfc2xpZGVfbnVtYmVyKHRoaXMuaHJlZik7CgogICAgICAgIGlmIChuZXdzbGlkZW51bSAhPSBzZWxmLnNsaWRlX251bWJlcikKICAgICAgICB7CiAgICAgICAgICB2YXIgc2xpZGUgPSBzZWxmLnNsaWRlc1tzZWxmLnNsaWRlX251bWJlcl07CiAgICAgICAgICBzZWxmLmhpZGVfc2xpZGUoc2xpZGUpOwogICAgICAgICAgc2VsZi5zbGlkZV9udW1iZXIgPSBuZXdzbGlkZW51bTsKICAgICAgICAgIHNsaWRlID0gc2VsZi5zbGlkZXNbc2VsZi5zbGlkZV9udW1iZXJdOwogICAgICAgICAgc2VsZi5zaG93X3NsaWRlKHNsaWRlKTsKICAgICAgICAgIHNlbGYuc2V0X2xvY2F0aW9uKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGVsc2UKICAgICAgICB3M2Nfc2xpZHkuc3RvcF9wcm9wYWdhdGlvbihldmVudCk7CgovLyAgICAgIGVsc2UgaWYgKHRoaXMudGFyZ2V0ID09IG51bGwpCi8vICAgICAgICBsb2NhdGlvbi5ocmVmID0gdGhpcy5ocmVmOwoKICAgICAgdGhpcy5ibHVyKCk7CiAgICAgIHNlbGYuZGlzYWJsZV9zbGlkZV9jbGljayA9IHRydWU7CiAgICB9OwoKICAgIHZhciBhbmNob3JzID0gZG9jdW1lbnQuYm9keS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiYSIpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYW5jaG9ycy5sZW5ndGg7ICsraSkKICAgIHsKICAgICAgaWYgKHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKQogICAgICAgIGFuY2hvcnNbaV0uYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCBoYW5kbGVyLCBmYWxzZSk7CiAgICAgIGVsc2UKICAgICAgICBhbmNob3JzW2ldLmF0dGFjaEV2ZW50KCJvbmNsaWNrIiwgaGFuZGxlcik7CiAgICB9CiAgfSwKCiAgLy8gIyMjIENIRUNLIE1FICMjIyBzZWUgd2hpY2ggZnVuY3Rpb25zIGFyZSBpbnZva2VkIHZpYSBzZXRUaW1lb3V0CiAgLy8gZWl0aGVyIGRpcmVjdGx5IG9yIGluZGlyZWN0bHkgZm9yIHVzZSBvZiB3M2Nfc2xpZHkgdnMgdGhpcwogIHNob3dfc2xpZGVfbnVtYmVyOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgdGltZXIgPSB3M2Nfc2xpZHkuZ2V0X3RpbWVyKCk7CiAgICB3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyX2VsZW1lbnQuaW5uZXJIVE1MID0gdGltZXIgKyB3M2Nfc2xpZHkubG9jYWxpemUoInNsaWRlIikgKyAiICIgKwogICAgICAgICAgICh3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyICsgMSkgKyAiLyIgKyB3M2Nfc2xpZHkuc2xpZGVzLmxlbmd0aDsKICB9LAoKICAvLyBldmVyeSAyMDBtUyBjaGVjayBpZiB0aGUgbG9jYXRpb24gaGFzIGJlZW4gY2hhbmdlZCBhcyBhCiAgLy8gcmVzdWx0IG9mIHRoZSB1c2VyIGFjdGl2YXRpbmcgdGhlIEJhY2sgYnV0dG9uL21lbnUgaXRlbQogIC8vIGRvZXNuJ3Qgd29yayBmb3IgT3BlcmEgPCA5LjUKICBjaGVja19sb2NhdGlvbjogZnVuY3Rpb24gKCkgewogICAgdmFyIGhhc2ggPSBsb2NhdGlvbi5oYXNoOwoKICAgIGlmICh3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyID4gMCAmJiAoaGFzaCA9PSAiIiB8fCBoYXNoID09ICIjIikpCiAgICAgIHczY19zbGlkeS5nb3RvX3NsaWRlKDApOwogICAgZWxzZSBpZiAoaGFzaC5sZW5ndGggPiAyICYmIGhhc2ggIT0gIiMoIisodzNjX3NsaWR5LnNsaWRlX251bWJlcisxKSsiKSIpCiAgICB7CiAgICAgIHZhciBudW0gPSBwYXJzZUludChsb2NhdGlvbi5oYXNoLnN1YnN0cigyKSk7CgogICAgICBpZiAoIWlzTmFOKG51bSkpCiAgICAgICAgdzNjX3NsaWR5LmdvdG9fc2xpZGUobnVtLTEpOwogICAgfQoKICAgIGlmICh3M2Nfc2xpZHkudGltZV9sZWZ0ICYmIHczY19zbGlkeS5zbGlkZV9udW1iZXIgPiAwKQogICAgewogICAgICB3M2Nfc2xpZHkuc2hvd19zbGlkZV9udW1iZXIoKTsKCiAgICAgIGlmICh3M2Nfc2xpZHkudGltZV9sZWZ0ID4gMCkKICAgICAgICB3M2Nfc2xpZHkudGltZV9sZWZ0IC09IDIwMDsKICAgIH0gCiAgfSwKCiAgZ2V0X3RpbWVyOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgdGltZXIgPSAiIjsKICAgIGlmICh3M2Nfc2xpZHkudGltZV9sZWZ0KQogICAgewogICAgICB2YXIgbWlucywgc2VjczsKICAgICAgc2VjcyA9IE1hdGguZmxvb3IodzNjX3NsaWR5LnRpbWVfbGVmdC8xMDAwKTsKICAgICAgbWlucyA9IE1hdGguZmxvb3Ioc2VjcyAvIDYwKTsKICAgICAgc2VjcyA9IHNlY3MgJSA2MDsKICAgICAgdGltZXIgPSAobWlucyA/IG1pbnMrIm0iIDogIiIpICsgc2VjcyArICJzICI7CiAgICB9CgogICAgcmV0dXJuIHRpbWVyOwogIH0sCgogIC8vIHRoaXMgZG9lc24ndCBwdXNoIGxvY2F0aW9uIG9udG8gaGlzdG9yeSBzdGFjayBmb3IgSUUKICAvLyBmb3Igd2hpY2ggYSBoaWRkZW4gaWZyYW1lIGhhY2sgaXMgbmVlZGVkOiBsb2FkIHBhZ2UgaW50bwogIC8vIHRoZSBpZnJhbWUgd2l0aCBzY3JpcHQgdGhhdCBzZXQncyBwYXJlbnQncyBsb2NhdGlvbi5oYXNoCiAgLy8gYnV0IHRoYXQgd29uJ3Qgd29yayBmb3Igc3RhbmRhbG9uZSB1c2UgdW5sZXNzIHdlIGNhbgogIC8vIGNyZWF0ZSB0aGUgcGFnZSBkeW5hbWljYWxseSB2aWEgYSBqYXZhc2NyaXB0OiBVUkwKICAvLyAjIyMgdXNlIGhpc3RvcnkucHVzaFN0YXRlIGlmIGF2YWlsYWJsZQogIHNldF9sb2NhdGlvbjogZnVuY3Rpb24gKCkgewogICAgIHZhciB1cmkgPSB3M2Nfc2xpZHkucGFnZV9hZGRyZXNzKGxvY2F0aW9uLmhyZWYpOwogICAgIHZhciBoYXNoID0gIiMoIiArICh3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyKzEpICsgIikiOwoKICAgICBpZiAodzNjX3NsaWR5LnNsaWRlX251bWJlciA+PSAwKQogICAgICAgdXJpID0gdXJpICsgaGFzaDsKCiAgICAgaWYgKHR5cGVvZihoaXN0b3J5LnB1c2hTdGF0ZSkgIT0gInVuZGVmaW5lZCIgJiYgbG9jYXRpb24ucHJvdG9jb2wgIT09ICJmaWxlOiIpCiAgICAgewogICAgICAgZG9jdW1lbnQudGl0bGUgPSB3M2Nfc2xpZHkudGl0bGUgKyAiICgiICsgKHczY19zbGlkeS5zbGlkZV9udW1iZXIrMSkgKyAiKSI7CiAgICAgICBoaXN0b3J5LnB1c2hTdGF0ZSgwLCBkb2N1bWVudC50aXRsZSwgaGFzaCk7CiAgICAgICB3M2Nfc2xpZHkuc2hvd19zbGlkZV9udW1iZXIoKTsKICAgICAgIHczY19zbGlkeS5ub3RpZnlfb2JzZXJ2ZXJzKCk7CiAgICAgICByZXR1cm47CiAgICAgfQoKICAgICBpZiAodzNjX3NsaWR5LmllICYmICh3M2Nfc2xpZHkuaWU2IHx8IHczY19zbGlkeS5pZTcpKQogICAgICAgdzNjX3NsaWR5LnB1c2hfaGFzaChoYXNoKTsKCiAgICAgaWYgKHVyaSAhPSBsb2NhdGlvbi5ocmVmKSAvLyAmJiAha2h0bWwKICAgICAgICBsb2NhdGlvbi5ocmVmID0gdXJpOwoKICAgICBpZiAodGhpcy5raHRtbCkKICAgICAgICBoYXNoID0gIigiICsgKHczY19zbGlkeS5zbGlkZV9udW1iZXIrMSkgKyAiKSI7CgogICAgIGlmICghdGhpcy5pZSAmJiBsb2NhdGlvbi5oYXNoICE9IGhhc2ggJiYgbG9jYXRpb24uaGFzaCAhPSAiIikKICAgICAgIGxvY2F0aW9uLmhhc2ggPSBoYXNoOwoKICAgICBkb2N1bWVudC50aXRsZSA9IHczY19zbGlkeS50aXRsZSArICIgKCIgKyAodzNjX3NsaWR5LnNsaWRlX251bWJlcisxKSArICIpIjsKICAgICB3M2Nfc2xpZHkuc2hvd19zbGlkZV9udW1iZXIoKTsKICAgICB3M2Nfc2xpZHkubm90aWZ5X29ic2VydmVycygpOwogIH0sCgogIG5vdGlmeV9vYnNlcnZlcnM6IGZ1bmN0aW9uICgpCiAgewogICAgdmFyIHNsaWRlID0gdGhpcy5zbGlkZXNbdGhpcy5zbGlkZV9udW1iZXJdOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5vYnNlcnZlcnMubGVuZ3RoOyArK2kpCiAgICAgIHRoaXMub2JzZXJ2ZXJzW2ldKHRoaXMuc2xpZGVfbnVtYmVyKzEsIHRoaXMuZmluZF9oZWFkaW5nKHNsaWRlKS5pbm5lclRleHQsIGxvY2F0aW9uLmhyZWYpOwogIH0sCgogIGFkZF9vYnNlcnZlcjogZnVuY3Rpb24gKG9ic2VydmVyKQogIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5vYnNlcnZlcnMubGVuZ3RoOyArK2kpCiAgICB7CiAgICAgIGlmIChvYnNlcnZlciA9PSB0aGlzLm9ic2VydmVyc1tpXSkKICAgICAgICByZXR1cm47CiAgICB9CgogICAgdGhpcy5vYnNlcnZlcnMucHVzaChvYnNlcnZlcik7CiAgfSwKCiAgcmVtb3ZlX29ic2VydmVyOiBmdW5jdGlvbiAobykKICB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMub2JzZXJ2ZXJzLmxlbmd0aDsgKytpKQogICAgewogICAgICBpZiAob2JzZXJ2ZXIgPT0gdGhpcy5vYnNlcnZlcnNbaV0pCiAgICAgIHsKICAgICAgICB0aGlzLm9ic2VydmVycy5zcGxpY2UoaSwxKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0sCgogIHBhZ2VfYWRkcmVzczogZnVuY3Rpb24gKHVyaSkgewogICAgdmFyIGkgPSB1cmkuaW5kZXhPZigiIyIpOwoKICAgIGlmIChpIDwgMCkKICAgICAgaSA9IHVyaS5pbmRleE9mKCIlMjMiKTsKCiAgICAvLyBjaGVjayBpZiBhbmNob3IgaXMgZW50aXJlIHBhZ2UKCiAgICBpZiAoaSA8IDApCiAgICAgIHJldHVybiB1cmk7ICAvLyB5ZXMKCiAgICByZXR1cm4gdXJpLnN1YnN0cigwLCBpKTsKICB9LAoKICAvLyBvbmx5IHVzZWQgZm9yIElFNiBhbmQgSUU3CiAgb25fZnJhbWVfbG9hZGVkOiBmdW5jdGlvbiAoaGFzaCkgewogICAgbG9jYXRpb24uaGFzaCA9IGhhc2g7CiAgICB2YXIgdXJpID0gdzNjX3NsaWR5LnBhZ2VfYWRkcmVzcyhsb2NhdGlvbi5ocmVmKTsKICAgIGxvY2F0aW9uLmhyZWYgPSB1cmkgKyBoYXNoOwogIH0sCgogIC8vIGhpc3RvcnkgaGFjayB3aXRoIHRoYW5rcyB0byBCZXJ0cmFuZCBMZSBSb3kKICBwdXNoX2hhc2g6IGZ1bmN0aW9uIChoYXNoKSB7CiAgICBpZiAoaGFzaCA9PSAiIikgaGFzaCA9ICIjKDEpIjsKICAgICAgd2luZG93LmxvY2F0aW9uLmhhc2ggPSBoYXNoOwoKICAgIHZhciBkb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiaGlzdG9yeUZyYW1lIikuY29udGVudFdpbmRvdy5kb2N1bWVudDsKICAgIGRvYy5vcGVuKCJqYXZhc2NyaXB0Oic8aHRtbD48L2h0bWw+JyIpOwogICAgZG9jLndyaXRlKCI8aHRtbD48aGVhZD48c2NyaXB0IHR5cGU9XCJ0ZXh0L2phdmFzY3JpcHRcIj53aW5kb3cucGFyZW50LnczY19zbGlkeS5vbl9mcmFtZV9sb2FkZWQoJyIrCiAgICAgIChoYXNoKSArICInKTs8L3NjcmlwdD48L2hlYWQ+PGJvZHk+aGVsbG8gbXVtPC9ib2R5PjwvaHRtbD4iKTsKICAgICAgZG9jLmNsb3NlKCk7CiAgfSwKCiAgLy8gZmluZCBjdXJyZW50IHNsaWRlIGJhc2VkIHVwb24gbG9jYXRpb24KICAvLyBmaXJzdCBmaW5kIHRhcmdldCBhbmNob3IgYW5kIHRoZW4gbG9vawogIC8vIGZvciBhc3NvY2lhdGVkIGRpdiBlbGVtZW50IGVuY2xvc2luZyBpdAogIC8vIGZpbmFsbHkgbWFwIHRoYXQgdG8gc2xpZGUgbnVtYmVyCiAgZmluZF9zbGlkZV9udW1iZXI6IGZ1bmN0aW9uICh1cmkpIHsKICAgIC8vIGZpcnN0IGdldCBhbmNob3IgZnJvbSBwYWdlIGxvY2F0aW9uCgogICAgdmFyIGkgPSB1cmkuaW5kZXhPZigiIyIpOwoKICAgIC8vIGNoZWNrIGlmIGFuY2hvciBpcyBlbnRpcmUgcGFnZQogICAgaWYgKGkgPCAwKQogICAgICByZXR1cm4gMDsgIC8vIHllcwoKICAgIHZhciBhbmNob3IgPSB1bmVzY2FwZSh1cmkuc3Vic3RyKGkrMSkpOwoKICAgIC8vIG5vdyB1c2UgYW5jaG9yIGFzIFhNTCBJRCB0byBmaW5kIHRhcmdldAogICAgdmFyIHRhcmdldCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGFuY2hvcik7CgogICAgaWYgKCF0YXJnZXQpCiAgICB7CiAgICAgIC8vIGRvZXMgYW5jaG9yIGxvb2sgbGlrZSAiKDIpIiBmb3Igc2xpZGUgMiA/PwogICAgICAvLyB3aGVyZSBmaXJzdCBzbGlkZSBpcyAoMSkKICAgICAgdmFyIHJlID0gL1woKFxkKStcKS87CgogICAgICBpZiAoYW5jaG9yLm1hdGNoKHJlKSkKICAgICAgewogICAgICAgIHZhciBudW0gPSBwYXJzZUludChhbmNob3Iuc3Vic3RyaW5nKDEsIGFuY2hvci5sZW5ndGgtMSkpOwoKICAgICAgICBpZiAobnVtID4gdGhpcy5zbGlkZXMubGVuZ3RoKQogICAgICAgICAgbnVtID0gMTsKCiAgICAgICAgaWYgKC0tbnVtIDwgMCkKICAgICAgICAgIG51bSA9IDA7CgogICAgICAgIHJldHVybiBudW07CiAgICAgIH0KCiAgICAgIC8vIGFjY2VwdCBbMl0gZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5CiAgICAgIHJlID0gL1xbKFxkKStcXS87CgogICAgICBpZiAoYW5jaG9yLm1hdGNoKHJlKSkKICAgICAgewogICAgICAgICB2YXIgbnVtID0gcGFyc2VJbnQoYW5jaG9yLnN1YnN0cmluZygxLCBhbmNob3IubGVuZ3RoLTEpKTsKCiAgICAgICAgIGlmIChudW0gPiB0aGlzLnNsaWRlcy5sZW5ndGgpCiAgICAgICAgICAgIG51bSA9IDE7CgogICAgICAgICBpZiAoLS1udW0gPCAwKQogICAgICAgICAgICBudW0gPSAwOwoKICAgICAgICAgcmV0dXJuIG51bTsKICAgICAgfQoKICAgICAgLy8gb2ggZGVhciB1bmtub3duIGFuY2hvcgogICAgICByZXR1cm4gMDsKICAgIH0KCiAgICAvLyBzZWFyY2ggZm9yIGVuY2xvc2luZyBzbGlkZQoKICAgIHdoaWxlICh0cnVlKQogICAgewogICAgICAvLyBicm93c2VyIGNvZXJjZXMgaHRtbCBlbGVtZW50cyB0byB1cHBlcmNhc2UhCiAgICAgIGlmICh0YXJnZXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PSAiZGl2IiAmJgogICAgICAgICAgICB0aGlzLmhhc19jbGFzcyh0YXJnZXQsICJzbGlkZSIpKQogICAgICB7CiAgICAgICAgLy8gZm91bmQgdGhlIHNsaWRlIGVsZW1lbnQKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgLy8gb3RoZXJ3aXNlIHRyeSBwYXJlbnQgZWxlbWVudCBpZiBhbnkKCiAgICAgIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlOwoKICAgICAgaWYgKCF0YXJnZXQpCiAgICAgIHsKICAgICAgICByZXR1cm4gMDsgICAvLyBubyBsdWNrIQogICAgICB9CiAgICB9OwoKICAgIGZvciAoaSA9IDA7IGkgPCBzbGlkZXMubGVuZ3RoOyArK2kpCiAgICB7CiAgICAgIGlmIChzbGlkZXNbaV0gPT0gdGFyZ2V0KQogICAgICAgIHJldHVybiBpOyAgLy8gc3VjY2VzcwogICAgfQoKICAgIC8vIG9oIGRlYXIgc3RpbGwgbm8gbHVjawogICAgcmV0dXJuIDA7CiAgfSwKCiAgcHJldmlvdXNfc2xpZGU6IGZ1bmN0aW9uIChpbmNyZW1lbnRhbCkgewogICAgaWYgKCF3M2Nfc2xpZHkudmlld19hbGwpCiAgICB7CiAgICAgIHZhciBzbGlkZTsKCiAgICAgIGlmICgoaW5jcmVtZW50YWwgfHwgdzNjX3NsaWR5LnNsaWRlX251bWJlciA9PSAwKSAmJiB3M2Nfc2xpZHkubGFzdF9zaG93biAhPSBudWxsKQogICAgICB7CiAgICAgICAgdzNjX3NsaWR5Lmxhc3Rfc2hvd24gPSB3M2Nfc2xpZHkuaGlkZV9wcmV2aW91c19pdGVtKHczY19zbGlkeS5sYXN0X3Nob3duKTsKICAgICAgICB3M2Nfc2xpZHkuc2V0X2Vvc19zdGF0dXMoZmFsc2UpOwogICAgICB9CiAgICAgIGVsc2UgaWYgKHczY19zbGlkeS5zbGlkZV9udW1iZXIgPiAwKQogICAgICB7CiAgICAgICAgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgICAgIHczY19zbGlkeS5oaWRlX3NsaWRlKHNsaWRlKTsKCiAgICAgICAgdzNjX3NsaWR5LnNsaWRlX251bWJlciA9IHczY19zbGlkeS5zbGlkZV9udW1iZXIgLSAxOwogICAgICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICB3M2Nfc2xpZHkuc2V0X3Zpc2liaWxpdHlfYWxsX2luY3JlbWVudGFsKCJ2aXNpYmxlIik7CiAgICAgICAgdzNjX3NsaWR5Lmxhc3Rfc2hvd24gPSB3M2Nfc2xpZHkucHJldmlvdXNfaW5jcmVtZW50YWxfaXRlbShudWxsKTsKICAgICAgICB3M2Nfc2xpZHkuc2V0X2Vvc19zdGF0dXModHJ1ZSk7CiAgICAgICAgdzNjX3NsaWR5LnNob3dfc2xpZGUoc2xpZGUpOwogICAgICB9CgogICAgICB3M2Nfc2xpZHkuc2V0X2xvY2F0aW9uKCk7CgogICAgICBpZiAoIXczY19zbGlkeS5uc19wb3MpCiAgICAgICAgdzNjX3NsaWR5LnJlZnJlc2hfdG9vbGJhcigyMDApOwogICAgfQogIH0sCgogIG5leHRfc2xpZGU6IGZ1bmN0aW9uIChpbmNyZW1lbnRhbCkgewogICAgaWYgKCF3M2Nfc2xpZHkudmlld19hbGwpCiAgICB7CiAgICAgIHZhciBzbGlkZSwgbGFzdCA9IHczY19zbGlkeS5sYXN0X3Nob3duOwoKICAgICAgaWYgKGluY3JlbWVudGFsIHx8IHczY19zbGlkeS5zbGlkZV9udW1iZXIgPT0gdzNjX3NsaWR5LnNsaWRlcy5sZW5ndGggLSAxKQogICAgICAgICB3M2Nfc2xpZHkubGFzdF9zaG93biA9IHczY19zbGlkeS5yZXZlYWxfbmV4dF9pdGVtKHczY19zbGlkeS5sYXN0X3Nob3duKTsKCiAgICAgIGlmICgoIWluY3JlbWVudGFsIHx8IHczY19zbGlkeS5sYXN0X3Nob3duID09IG51bGwpICYmCiAgICAgICAgICAgICB3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyIDwgdzNjX3NsaWR5LnNsaWRlcy5sZW5ndGggLSAxKQogICAgICB7CiAgICAgICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICAgdzNjX3NsaWR5LmhpZGVfc2xpZGUoc2xpZGUpOwoKICAgICAgICAgdzNjX3NsaWR5LnNsaWRlX251bWJlciA9IHczY19zbGlkeS5zbGlkZV9udW1iZXIgKyAxOwogICAgICAgICBzbGlkZSA9IHczY19zbGlkeS5zbGlkZXNbdzNjX3NsaWR5LnNsaWRlX251bWJlcl07CiAgICAgICAgIHczY19zbGlkeS5sYXN0X3Nob3duID0gbnVsbDsKICAgICAgICAgdzNjX3NsaWR5LnNldF92aXNpYmlsaXR5X2FsbF9pbmNyZW1lbnRhbCgiaGlkZGVuIik7CiAgICAgICAgIHczY19zbGlkeS5zaG93X3NsaWRlKHNsaWRlKTsKICAgICAgfQogICAgICBlbHNlIGlmICghdzNjX3NsaWR5Lmxhc3Rfc2hvd24pCiAgICAgIHsKICAgICAgICAgaWYgKGxhc3QgJiYgaW5jcmVtZW50YWwpCiAgICAgICAgICAgdzNjX3NsaWR5Lmxhc3Rfc2hvd24gPSBsYXN0OwogICAgICB9CgogICAgICB3M2Nfc2xpZHkuc2V0X2xvY2F0aW9uKCk7CgogICAgICB3M2Nfc2xpZHkuc2V0X2Vvc19zdGF0dXMoIXczY19zbGlkeS5uZXh0X2luY3JlbWVudGFsX2l0ZW0odzNjX3NsaWR5Lmxhc3Rfc2hvd24pKTsKCiAgICAgIGlmICghdzNjX3NsaWR5Lm5zX3BvcykKICAgICAgICAgdzNjX3NsaWR5LnJlZnJlc2hfdG9vbGJhcigyMDApOwogICAgIH0KICB9LAoKICAvLyB0byBmaXJzdCBzbGlkZSB3aXRoIG5vdGhpbmcgcmV2ZWFsZWQKICAvLyBpLmUuIHN0YXRlIGF0IHN0YXJ0IG9mIHByZXNlbnRhdGlvbgogIGZpcnN0X3NsaWRlOiBmdW5jdGlvbiAoKSB7CiAgICAgaWYgKCF3M2Nfc2xpZHkudmlld19hbGwpCiAgICAgewogICAgICAgdmFyIHNsaWRlOwoKICAgICAgIGlmICh3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyICE9IDApCiAgICAgICB7CiAgICAgICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICAgdzNjX3NsaWR5LmhpZGVfc2xpZGUoc2xpZGUpOwoKICAgICAgICAgdzNjX3NsaWR5LnNsaWRlX251bWJlciA9IDA7CiAgICAgICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICAgdzNjX3NsaWR5Lmxhc3Rfc2hvd24gPSBudWxsOwogICAgICAgICB3M2Nfc2xpZHkuc2V0X3Zpc2liaWxpdHlfYWxsX2luY3JlbWVudGFsKCJoaWRkZW4iKTsKICAgICAgICAgdzNjX3NsaWR5LnNob3dfc2xpZGUoc2xpZGUpOwogICAgICAgfQoKICAgICAgIHczY19zbGlkeS5zZXRfZW9zX3N0YXR1cygKICAgICAgICAgIXczY19zbGlkeS5uZXh0X2luY3JlbWVudGFsX2l0ZW0odzNjX3NsaWR5Lmxhc3Rfc2hvd24pKTsKICAgICAgIHczY19zbGlkeS5zZXRfbG9jYXRpb24oKTsKICAgICB9CiAgfSwKCiAgLy8gZ290byBsYXN0IHNsaWRlIHdpdGggZXZlcnl0aGluZyByZXZlYWxlZAogIC8vIGkuZS4gc3RhdGUgYXQgZW5kIG9mIHByZXNlbnRhdGlvbgogIGxhc3Rfc2xpZGU6IGZ1bmN0aW9uICgpIHsKICAgIGlmICghdzNjX3NsaWR5LnZpZXdfYWxsKQogICAgewogICAgICB2YXIgc2xpZGU7CgogICAgICB3M2Nfc2xpZHkubGFzdF9zaG93biA9IG51bGw7IC8vcmV2ZWFsTmV4dEl0ZW0obGFzdFNob3duKTsKCiAgICAgIGlmICh3M2Nfc2xpZHkubGFzdF9zaG93biA9PSBudWxsICYmCiAgICAgICAgICB3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyIDwgdzNjX3NsaWR5LnNsaWRlcy5sZW5ndGggLSAxKQogICAgICB7CiAgICAgICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgICAgICAgdzNjX3NsaWR5LmhpZGVfc2xpZGUoc2xpZGUpOwogICAgICAgICB3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyID0gdzNjX3NsaWR5LnNsaWRlcy5sZW5ndGggLSAxOwogICAgICAgICBzbGlkZSA9IHczY19zbGlkeS5zbGlkZXNbdzNjX3NsaWR5LnNsaWRlX251bWJlcl07CiAgICAgICAgIHczY19zbGlkeS5zZXRfdmlzaWJpbGl0eV9hbGxfaW5jcmVtZW50YWwoInZpc2libGUiKTsKICAgICAgICAgdzNjX3NsaWR5Lmxhc3Rfc2hvd24gPSB3M2Nfc2xpZHkucHJldmlvdXNfaW5jcmVtZW50YWxfaXRlbShudWxsKTsKCiAgICAgICAgIHczY19zbGlkeS5zaG93X3NsaWRlKHNsaWRlKTsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICAgdzNjX3NsaWR5LnNldF92aXNpYmlsaXR5X2FsbF9pbmNyZW1lbnRhbCgidmlzaWJsZSIpOwogICAgICAgICB3M2Nfc2xpZHkubGFzdF9zaG93biA9IHczY19zbGlkeS5wcmV2aW91c19pbmNyZW1lbnRhbF9pdGVtKG51bGwpOwogICAgICB9CgogICAgICB3M2Nfc2xpZHkuc2V0X2Vvc19zdGF0dXModHJ1ZSk7CiAgICAgIHczY19zbGlkeS5zZXRfbG9jYXRpb24oKTsKICAgIH0KICB9LAoKCiAgLy8gIyMjIGNoZWNrIHRoaXMgYW5kIGNvbnNpZGVyIGFkZC9yZW1vdmUgY2xhc3MKICBzZXRfZW9zX3N0YXR1czogZnVuY3Rpb24gKHN0YXRlKSB7CiAgICBpZiAodGhpcy5lb3MpCiAgICAgIHRoaXMuZW9zLnN0eWxlLmNvbG9yID0gKHN0YXRlID8gInJnYigyNDAsMjQwLDI0MCkiIDogInJlZCIpOwogIH0sCgogIC8vIGZpcnN0IHNsaWRlIGlzIDAKICBnb3RvX3NsaWRlOiBmdW5jdGlvbiAobnVtKSB7CiAgICAvL2FsZXJ0KCJnb2luZyB0byBzbGlkZSAiICsgKG51bSsxKSk7CiAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgdzNjX3NsaWR5LmhpZGVfc2xpZGUoc2xpZGUpOwogICAgdzNjX3NsaWR5LnNsaWRlX251bWJlciA9IG51bTsKICAgIHNsaWRlID0gdzNjX3NsaWR5LnNsaWRlc1t3M2Nfc2xpZHkuc2xpZGVfbnVtYmVyXTsKICAgIHczY19zbGlkeS5sYXN0X3Nob3duID0gbnVsbDsKICAgIHczY19zbGlkeS5zZXRfdmlzaWJpbGl0eV9hbGxfaW5jcmVtZW50YWwoImhpZGRlbiIpOwogICAgdzNjX3NsaWR5LnNldF9lb3Nfc3RhdHVzKCF3M2Nfc2xpZHkubmV4dF9pbmNyZW1lbnRhbF9pdGVtKHczY19zbGlkeS5sYXN0X3Nob3duKSk7CiAgICBkb2N1bWVudC50aXRsZSA9IHczY19zbGlkeS50aXRsZSArICIgKCIgKyAodzNjX3NsaWR5LnNsaWRlX251bWJlcisxKSArICIpIjsKICAgIHczY19zbGlkeS5zaG93X3NsaWRlKHNsaWRlKTsKICAgIHczY19zbGlkeS5zaG93X3NsaWRlX251bWJlcigpOwogIH0sCgoKICBzaG93X3NsaWRlOiBmdW5jdGlvbiAoc2xpZGUpIHsKICAgIHRoaXMuc3luY19iYWNrZ3JvdW5kKHNsaWRlKTsKICAgIHRoaXMucmVtb3ZlX2NsYXNzKHNsaWRlLCAiaGlkZGVuIik7CgogICAgLy8gd29yayBhcm91bmQgSUU5IG9iamVjdCByZW5kZXJpbmcgYnVnCiAgICBzZXRUaW1lb3V0KCJ3aW5kb3cuc2Nyb2xsVG8oMCwwKTsiLCAxKTsKICB9LAoKICBoaWRlX3NsaWRlOiBmdW5jdGlvbiAoc2xpZGUpIHsKICAgIHRoaXMuYWRkX2NsYXNzKHNsaWRlLCAiaGlkZGVuIik7CiAgfSwKCiAgc2V0X2ZvY3VzOiBmdW5jdGlvbiAoZWxlbWVudCkKICB7CiAgICBpZiAoZWxlbWVudCkKICAgICAgZWxlbWVudC5mb2N1cygpOwogICAgZWxzZQogICAgewogICAgICB3M2Nfc2xpZHkuaGVscF9hbmNob3IuZm9jdXMoKTsKCiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7CiAgICAgICAgdzNjX3NsaWR5LmhlbHBfYW5jaG9yLmJsdXIoKTsKICAgICAgfSwgMSk7CiAgICB9CiAgfSwKCiAgLy8gc2hvdyBqdXN0IHRoZSBiYWNrZ3JvdW5kcyBwZXJ0aW5lbnQgdG8gdGhpcyBzbGlkZQogIC8vIHdoZW4gc2xpZGUgYmFja2dyb3VuZC1jb2xvciBpcyB0cmFuc3BhcmVudAogIC8vIHRoaXMgc2hvdWxkIG5vdyB3b3JrIHdpdGggcmdiYSBjb2xvciB2YWx1ZXMKICBzeW5jX2JhY2tncm91bmQ6IGZ1bmN0aW9uIChzbGlkZSkgewogICAgdmFyIGJhY2tncm91bmQ7CiAgICB2YXIgYmdDb2xvcjsKCiAgICBpZiAoc2xpZGUuY3VycmVudFN0eWxlKQogICAgICBiZ0NvbG9yID0gc2xpZGUuY3VycmVudFN0eWxlWyJiYWNrZ3JvdW5kQ29sb3IiXTsKICAgIGVsc2UgaWYgKGRvY3VtZW50LmRlZmF1bHRWaWV3KQogICAgewogICAgICB2YXIgc3R5bGVzID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShzbGlkZSxudWxsKTsKCiAgICAgIGlmIChzdHlsZXMpCiAgICAgICAgYmdDb2xvciA9IHN0eWxlcy5nZXRQcm9wZXJ0eVZhbHVlKCJiYWNrZ3JvdW5kLWNvbG9yIik7CiAgICAgIGVsc2UgLy8gYnJva2VuIGltcGxlbWVudGF0aW9uIHByb2JhYmx5IGR1ZSBTYWZhcmkgb3IgS29ucXVlcm9yCiAgICAgIHsKICAgICAgICAvL2FsZXJ0KCJkZWZlY3RpdmUgaW1wbGVtZW50YXRpb24gb2YgZ2V0Q29tcHV0ZWRTdHlsZSgpIik7CiAgICAgICAgYmdDb2xvciA9ICJ0cmFuc3BhcmVudCI7CiAgICAgIH0KICAgIH0KICAgIGVsc2UKICAgICAgYmdDb2xvciA9PSAidHJhbnNwYXJlbnQiOwoKICAgIGlmIChiZ0NvbG9yID09ICJ0cmFuc3BhcmVudCIgfHwKICAgICAgICBiZ0NvbG9yLmluZGV4T2YoInJnYmEiKSA+PSAwIHx8CiAgICAgICAgYmdDb2xvci5pbmRleE9mKCJvcGFjaXR5IikgPj0gMCkKICAgIHsKICAgICAgdmFyIHNsaWRlQ2xhc3MgPSB0aGlzLmdldF9jbGFzc19saXN0KHNsaWRlKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5iYWNrZ3JvdW5kcy5sZW5ndGg7IGkrKykKICAgICAgewogICAgICAgIGJhY2tncm91bmQgPSB0aGlzLmJhY2tncm91bmRzW2ldOwoKICAgICAgICB2YXIgYmdDbGFzcyA9IHRoaXMuZ2V0X2NsYXNzX2xpc3QoYmFja2dyb3VuZCk7CgogICAgICAgIGlmICh0aGlzLm1hdGNoaW5nX2JhY2tncm91bmQoc2xpZGVDbGFzcywgYmdDbGFzcykpCiAgICAgICAgICB0aGlzLnJlbW92ZV9jbGFzcyhiYWNrZ3JvdW5kLCAiaGlkZGVuIik7CiAgICAgICAgZWxzZQogICAgICAgICAgdGhpcy5hZGRfY2xhc3MoYmFja2dyb3VuZCwgImhpZGRlbiIpOwogICAgICB9CiAgICB9CiAgICBlbHNlIC8vIGZvcmNpYmx5IGhpZGUgYWxsIGJhY2tncm91bmRzCiAgICAgIHRoaXMuaGlkZV9iYWNrZ3JvdW5kcygpOwogIH0sCgogIGhpZGVfYmFja2dyb3VuZHM6IGZ1bmN0aW9uICgpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5iYWNrZ3JvdW5kcy5sZW5ndGg7IGkrKykKICAgIHsKICAgICAgYmFja2dyb3VuZCA9IHRoaXMuYmFja2dyb3VuZHNbaV07CiAgICAgIHRoaXMuYWRkX2NsYXNzKGJhY2tncm91bmQsICJoaWRkZW4iKTsKICAgIH0KICB9LAoKICAvLyBjb21wYXJlIGNsYXNzZXMgZm9yIHNsaWRlIGFuZCBiYWNrZ3JvdW5kCiAgbWF0Y2hpbmdfYmFja2dyb3VuZDogZnVuY3Rpb24gKHNsaWRlQ2xhc3MsIGJnQ2xhc3MpIHsKICAgIHZhciBpLCBjb3VudCwgcGF0dGVybiwgcmVzdWx0OwoKICAgIC8vIGRlZmluZSBwYXR0ZXJuIGFzIHJlZ3VsYXIgZXhwcmVzc2lvbgogICAgcGF0dGVybiA9IC9cdysvZzsKCiAgICAvLyBjaGVjayBiYWNrZ3JvdW5kIGNsYXNzIG5hbWVzCiAgICByZXN1bHQgPSBiZ0NsYXNzLm1hdGNoKHBhdHRlcm4pOwoKICAgIGZvciAoaSA9IGNvdW50ID0gMDsgaSA8IHJlc3VsdC5sZW5ndGg7IGkrKykKICAgIHsKICAgICAgaWYgKHJlc3VsdFtpXSA9PSAiaGlkZGVuIikKICAgICAgICBjb250aW51ZTsKCiAgICAgIGlmIChyZXN1bHRbaV0gPT0gImJhY2tncm91bmQiKQoJY29udGludWU7CgogICAgICArK2NvdW50OwogICAgfQoKICAgIGlmIChjb3VudCA9PSAwKSAgLy8gZGVmYXVsdCBtYXRjaAogICAgICByZXR1cm4gdHJ1ZTsKCiAgICAvLyBjaGVjayBmb3IgbWF0Y2hlcyBhbmQgcGxhY2UgcmVzdWx0IGluIGFycmF5CiAgICByZXN1bHQgPSBzbGlkZUNsYXNzLm1hdGNoKHBhdHRlcm4pOwoKICAgIC8vIG5vdyBjaGVjayBpZiBkZXNpcmVkIG5hbWUgaXMgcHJlc2VudCBmb3IgYmFja2dyb3VuZAogICAgZm9yIChpID0gY291bnQgPSAwOyBpIDwgcmVzdWx0Lmxlbmd0aDsgaSsrKQogICAgewogICAgICBpZiAocmVzdWx0W2ldID09ICJoaWRkZW4iKQogICAgICAgIGNvbnRpbnVlOwoKICAgICAgaWYgKHRoaXMuaGFzX3Rva2VuKGJnQ2xhc3MsIHJlc3VsdFtpXSkpCiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0sCgogIHJlc2l6ZWQ6IGZ1bmN0aW9uICgpIHsKICAgICB2YXIgd2lkdGggPSAwOwoKICAgICBpZiAoIHR5cGVvZiggd2luZG93LmlubmVyV2lkdGggKSA9PSAnbnVtYmVyJyApCiAgICAgICB3aWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoOyAgLy8gTm9uIElFIGJyb3dzZXIKICAgICBlbHNlIGlmIChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoKQogICAgICAgd2lkdGggPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGg7ICAvLyBJRTYKICAgICBlbHNlIGlmIChkb2N1bWVudC5ib2R5ICYmIGRvY3VtZW50LmJvZHkuY2xpZW50V2lkdGgpCiAgICAgICB3aWR0aCA9IGRvY3VtZW50LmJvZHkuY2xpZW50V2lkdGg7IC8vIElFNAoKICAgICB2YXIgaGVpZ2h0ID0gMDsKCiAgICAgaWYgKCB0eXBlb2YoIHdpbmRvdy5pbm5lckhlaWdodCApID09ICdudW1iZXInICkKICAgICAgIGhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodDsgIC8vIE5vbiBJRSBicm93c2VyCiAgICAgZWxzZSBpZiAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpCiAgICAgICBoZWlnaHQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0OyAgLy8gSUU2CiAgICAgZWxzZSBpZiAoZG9jdW1lbnQuYm9keSAmJiBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodCkKICAgICAgIGhlaWdodCA9IGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0OyAvLyBJRTQKCiAgICAgaWYgKGhlaWdodCAmJiAod2lkdGgvaGVpZ2h0ID4gMS4wNSoxMDI0Lzc2OCkpCiAgICAgewogICAgICAgd2lkdGggPSBoZWlnaHQgKiAxMDI0LjAvNzY4OwogICAgIH0KCiAgICAgLy8gSUUgZmlyZXMgb25yZXNpemUgZXZlbiB3aGVuIG9ubHkgZm9udCBzaXplIGlzIGNoYW5nZWQhCiAgICAgLy8gc28gd2UgZG8gYSBjaGVjayB0byBhdm9pZCBibG9ja2luZyA8IGFuZCA+IGFjdGlvbnMKICAgICBpZiAod2lkdGggIT0gdzNjX3NsaWR5Lmxhc3Rfd2lkdGggfHwgaGVpZ2h0ICE9IHczY19zbGlkeS5sYXN0X2hlaWdodCkKICAgICB7CiAgICAgICBpZiAod2lkdGggPj0gMTEwMCkKICAgICAgICAgdzNjX3NsaWR5LnNpemVfaW5kZXggPSA1OyAgICAvLyA0CiAgICAgICBlbHNlIGlmICh3aWR0aCA+PSAxMDAwKQogICAgICAgICB3M2Nfc2xpZHkuc2l6ZV9pbmRleCA9IDQ7ICAgIC8vIDMKICAgICAgIGVsc2UgaWYgKHdpZHRoID49IDgwMCkKICAgICAgICAgdzNjX3NsaWR5LnNpemVfaW5kZXggPSAzOyAgICAvLyAyCiAgICAgICBlbHNlIGlmICh3aWR0aCA+PSA2MDApCiAgICAgICAgIHczY19zbGlkeS5zaXplX2luZGV4ID0gMjsgICAgLy8gMQogICAgICAgZWxzZSBpZiAod2lkdGgpCiAgICAgICAgIHczY19zbGlkeS5zaXplX2luZGV4ID0gMDsKCiAgICAgICAvLyBhZGQgaW4gZm9udCBzaXplIGFkanVzdG1lbnQgZnJvbSBtZXRhIGVsZW1lbnQgZS5nLgogICAgICAgLy8gPG1ldGEgbmFtZT0iZm9udC1zaXplLWFkanVzdG1lbnQiIGNvbnRlbnQ9Ii0yIiAvPgogICAgICAgLy8gdXNlZnVsIHdoZW4gc2xpZGVzIGhhdmUgdG9vIG11Y2ggY29udGVudCA7LSkKCiAgICAgICBpZiAoMCA8PSB3M2Nfc2xpZHkuc2l6ZV9pbmRleCArIHczY19zbGlkeS5zaXplX2FkanVzdG1lbnQgJiYKICAgICAgICAgICAgIHczY19zbGlkeS5zaXplX2luZGV4ICsgdzNjX3NsaWR5LnNpemVfYWRqdXN0bWVudCA8IHczY19zbGlkeS5zaXplcy5sZW5ndGgpCiAgICAgICAgIHczY19zbGlkeS5zaXplX2luZGV4ID0gdzNjX3NsaWR5LnNpemVfaW5kZXggKyB3M2Nfc2xpZHkuc2l6ZV9hZGp1c3RtZW50OwoKICAgICAgIC8vIGVuYWJsZXMgY3Jvc3MgYnJvd3NlciB1c2Ugb2YgcmVsYXRpdmUgd2lkdGgvaGVpZ2h0CiAgICAgICAvLyBvbiBvYmplY3QgZWxlbWVudHMgZm9yIHVzZSB3aXRoIFNWRyBhbmQgRmxhc2ggbWVkaWEKICAgICAgIHczY19zbGlkeS5hZGp1c3Rfb2JqZWN0X2RpbWVuc2lvbnMod2lkdGgsIGhlaWdodCk7CgogICAgICAgaWYgKGRvY3VtZW50LmJvZHkuc3R5bGUuZm9udFNpemUgIT0gdzNjX3NsaWR5LnNpemVzW3czY19zbGlkeS5zaXplX2luZGV4XSkKICAgICAgIHsKICAgICAgICAgZG9jdW1lbnQuYm9keS5zdHlsZS5mb250U2l6ZSA9IHczY19zbGlkeS5zaXplc1t3M2Nfc2xpZHkuc2l6ZV9pbmRleF07CiAgICAgICB9CgogICAgICAgdzNjX3NsaWR5Lmxhc3Rfd2lkdGggPSB3aWR0aDsKICAgICAgIHczY19zbGlkeS5sYXN0X2hlaWdodCA9IGhlaWdodDsKCiAgICAgICAvLyBmb3JjZSByZWZsb3cgdG8gd29yayBhcm91bmQgTW96aWxsYSBidWcKICAgICAgIGlmICh3M2Nfc2xpZHkubnNfcG9zKQogICAgICAgewogICAgICAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgICAgICB3M2Nfc2xpZHkuaGlkZV9zbGlkZShzbGlkZSk7CiAgICAgICAgIHczY19zbGlkeS5zaG93X3NsaWRlKHNsaWRlKTsKICAgICAgIH0KCiAgICAgICAvLyBmb3JjZSBjb3JyZWN0IHBvc2l0aW9uaW5nIG9mIHRvb2xiYXIKICAgICAgIHczY19zbGlkeS5yZWZyZXNoX3Rvb2xiYXIoMjAwKTsKICAgICB9CiAgfSwKCiAgc2Nyb2xsZWQ6IGZ1bmN0aW9uICgpIHsKICAgIGlmICh3M2Nfc2xpZHkudG9vbGJhciAmJiAhdzNjX3NsaWR5Lm5zX3BvcyAmJiAhdzNjX3NsaWR5LmllNykKICAgIHsKICAgICAgdzNjX3NsaWR5LmhhY2tfb2Zmc2V0ID0gdzNjX3NsaWR5LnNjcm9sbF94X29mZnNldCgpOwogICAgICAvLyBoaWRlIHRvb2xiYXIKICAgICAgdzNjX3NsaWR5LnRvb2xiYXIuc3R5bGUuZGlzcGxheSA9ICJub25lIjsKCiAgICAgIC8vIG1ha2UgaXQgcmVhcHBlYXIgbGF0ZXIKICAgICAgaWYgKHczY19zbGlkeS5zY3JvbGxoYWNrID09IDAgJiYgIXczY19zbGlkeS52aWV3X2FsbCkKICAgICAgewogICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge3czY19zbGlkeS5zaG93X3Rvb2xiYXIoKTsgfSwgMTAwMCk7CiAgICAgICAgdzNjX3NsaWR5LnNjcm9sbGhhY2sgPSAxOwogICAgICB9CiAgICB9CiAgfSwKCiAgaGlkZV90b29sYmFyOiBmdW5jdGlvbiAoKSB7CiAgICB3M2Nfc2xpZHkuYWRkX2NsYXNzKHczY19zbGlkeS50b29sYmFyLCAiaGlkZGVuIik7CiAgICB3aW5kb3cuZm9jdXMoKTsKICB9LAoKICAvLyB1c2VkIHRvIGVuc3VyZSBJRSByZWZyZXNoZXMgdG9vbGJhciBpbiBjb3JyZWN0IHBvc2l0aW9uCiAgcmVmcmVzaF90b29sYmFyOiBmdW5jdGlvbiAoaW50ZXJ2YWwpIHsKICAgIGlmICghdzNjX3NsaWR5Lm5zX3BvcyAmJiAhdzNjX3NsaWR5LmllNykKICAgIHsKICAgICAgdzNjX3NsaWR5LmhpZGVfdG9vbGJhcigpOwogICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHt3M2Nfc2xpZHkuc2hvd190b29sYmFyKCk7fSwgaW50ZXJ2YWwpOwogICAgfQogIH0sCgogIC8vIHJlc3RvcmVzIHRvb2xiYXIgYWZ0ZXIgc2hvcnQgZGVsYXkKICBzaG93X3Rvb2xiYXI6IGZ1bmN0aW9uICgpIHsKICAgIGlmICh3M2Nfc2xpZHkud2FudF90b29sYmFyKQogICAgewogICAgICB3M2Nfc2xpZHkudG9vbGJhci5zdHlsZS5kaXNwbGF5ID0gImJsb2NrIjsKCiAgICAgIGlmICghdzNjX3NsaWR5Lm5zX3BvcykKICAgICAgewogICAgICAgIC8vIGFkanVzdCBwb3NpdGlvbiB0byBhbGxvdyBmb3Igc2Nyb2xsaW5nCiAgICAgICAgdmFyIHhvZmZzZXQgPSB3M2Nfc2xpZHkuc2Nyb2xsX3hfb2Zmc2V0KCk7CiAgICAgICAgdzNjX3NsaWR5LnRvb2xiYXIuc3R5bGUubGVmdCA9IHhvZmZzZXQ7CiAgICAgICAgdzNjX3NsaWR5LnRvb2xiYXIuc3R5bGUucmlnaHQgPSB4b2Zmc2V0OwoKICAgICAgICAvLyBkZXRlcm1pbmUgdmVydGljYWwgc2Nyb2xsIG9mZnNldAogICAgICAgIC8vdmFyIHlvZmZzZXQgPSBzY3JvbGxZT2Zmc2V0KCk7CgogICAgICAgIC8vIGJvdHRvbSBpcyBkb2MgaGVpZ2h0IC0gd2luZG93IGhlaWdodCAtIHNjcm9sbCBvZmZzZXQKICAgICAgICAvL3ZhciBib3R0b20gPSBkb2N1bWVudEhlaWdodCgpIC0gbGFzdEhlaWdodCAtIHlvZmZzZXQKCiAgICAgICAgLy9pZiAoeW9mZnNldCA+IDAgfHwgZG9jdW1lbnRIZWlnaHQoKSA+IGxhc3RIZWlnaHQpCiAgICAgICAgLy8gICBib3R0b20gKz0gMTY7ICAvLyBhbGxvdyBmb3IgaGVpZ2h0IG9mIHNjcm9sbGJhcgoKICAgICAgICB3M2Nfc2xpZHkudG9vbGJhci5zdHlsZS5ib3R0b20gPSAwOyAvL2JvdHRvbTsKICAgICAgfQoKICAgICAgdzNjX3NsaWR5LnJlbW92ZV9jbGFzcyh3M2Nfc2xpZHkudG9vbGJhciwgImhpZGRlbiIpOwogICAgfQoKICAgIHczY19zbGlkeS5zY3JvbGxoYWNrID0gMDsKCgogICAgLy8gc2V0IHRoZSBrZXlib2FyZCBmb2N1cyB0byB0aGUgaGVscCBsaW5rIG9uIHRoZQogICAgLy8gdG9vbGJhciB0byBlbnN1cmUgdGhhdCBkb2N1bWVudCBoYXMgdGhlIGZvY3VzCiAgICAvLyBJRSBkb2Vzbid0IGFsd2F5cyB3b3JrIHdpdGggd2luZG93LmZvY3VzKCkKICAgIC8vIGFuZCB0aGlzIGhhY2sgaGFzIGJlbmVmaXQgb2YgRW50ZXIgZm9yIGhlbHAKCiAgICB0cnkKICAgIHsKICAgICAgaWYgKCF3M2Nfc2xpZHkub3BlcmEpCiAgICAgICAgdzNjX3NsaWR5LnNldF9mb2N1cygpOwogICAgfQogICAgY2F0Y2ggKGUpCiAgICB7CiAgICB9CiAgfSwKCi8vIGludm9rZWQgdmlhIEYga2V5CiAgdG9nZ2xlX3Rvb2xiYXI6IGZ1bmN0aW9uICgpIHsKICAgIGlmICghdzNjX3NsaWR5LnZpZXdfYWxsKQogICAgewogICAgICBpZiAodzNjX3NsaWR5Lmhhc19jbGFzcyh3M2Nfc2xpZHkudG9vbGJhciwgImhpZGRlbiIpKQogICAgICB7CiAgICAgICAgdzNjX3NsaWR5LnJlbW92ZV9jbGFzcyh3M2Nfc2xpZHkudG9vbGJhciwgImhpZGRlbiIpCiAgICAgICAgdzNjX3NsaWR5LndhbnRfdG9vbGJhciA9IDE7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgdzNjX3NsaWR5LmFkZF9jbGFzcyh3M2Nfc2xpZHkudG9vbGJhciwgImhpZGRlbiIpCiAgICAgICAgdzNjX3NsaWR5LndhbnRfdG9vbGJhciA9IDA7CiAgICAgIH0KICAgIH0KICB9LAoKICBzY3JvbGxfeF9vZmZzZXQ6IGZ1bmN0aW9uICgpIHsKICAgIGlmICh3aW5kb3cucGFnZVhPZmZzZXQpCiAgICAgIHJldHVybiBzZWxmLnBhZ2VYT2Zmc2V0OwoKICAgIGlmIChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgCiAgICAgICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdCkKICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0OwoKICAgIGlmIChkb2N1bWVudC5ib2R5KQogICAgICByZXR1cm4gZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0OwoKICAgIHJldHVybiAwOwogIH0sCgogIHNjcm9sbF95X29mZnNldDogZnVuY3Rpb24gKCkgewogICAgaWYgKHdpbmRvdy5wYWdlWU9mZnNldCkKICAgICAgcmV0dXJuIHNlbGYucGFnZVlPZmZzZXQ7CgogICAgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiAKICAgICAgICAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3ApCiAgICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wOwoKICAgIGlmIChkb2N1bWVudC5ib2R5KQogICAgICByZXR1cm4gZG9jdW1lbnQuYm9keS5zY3JvbGxUb3A7CgogICAgcmV0dXJuIDA7CiAgfSwKCiAgLy8gbG9va2luZyBmb3IgYSB3YXkgdG8gZGV0ZXJtaW5lIGhlaWdodCBvZiBzbGlkZSBjb250ZW50CiAgLy8gdGhlIHNsaWRlIGl0c2VsZiBpcyBzZXQgdG8gdGhlIGhlaWdodCBvZiB0aGUgd2luZG93CiAgb3B0aW1pemVfZm9udF9zaXplOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwoKICAgIC8vdmFyIGRoID0gZG9jdW1lbnRIZWlnaHQoKTsgLy9nZXREb2NIZWlnaHQoZG9jdW1lbnQpOwogICAgdmFyIGRoID0gc2xpZGUuc2Nyb2xsSGVpZ2h0OwogICAgdmFyIHdoID0gZ2V0V2luZG93SGVpZ2h0KCk7CiAgICB2YXIgdSA9IDEwMCAqIGRoIC8gd2g7CgogICAgYWxlcnQoIndpbmRvdyB1dGlsaXphdGlvbiA9ICIgKyB1ICsgIiUgKGRvYyAiCiAgICAgICsgZGggKyAiIHdpbiAiICsgd2ggKyAiKSIpOwogIH0sCgogIC8vIGZyb20gZG9jdW1lbnQgb2JqZWN0CiAgZ2V0X2RvY19oZWlnaHQ6IGZ1bmN0aW9uIChkb2MpIHsKICAgIGlmICghZG9jKQogICAgICBkb2MgPSBkb2N1bWVudDsKCiAgICBpZiAoZG9jICYmIGRvYy5ib2R5ICYmIGRvYy5ib2R5Lm9mZnNldEhlaWdodCkKICAgICAgcmV0dXJuIGRvYy5ib2R5Lm9mZnNldEhlaWdodDsgIC8vIG5zL2dlY2tvIHN5bnRheAoKICAgIGlmIChkb2MgJiYgZG9jLmJvZHkgJiYgZG9jLmJvZHkuc2Nyb2xsSGVpZ2h0KQogICAgICByZXR1cm4gZG9jLmJvZHkuc2Nyb2xsSGVpZ2h0OwoKICAgIGFsZXJ0KCJjb3VsZG4ndCBkZXRlcm1pbmUgZG9jdW1lbnQgaGVpZ2h0Iik7CiAgfSwKCiAgZ2V0X3dpbmRvd19oZWlnaHQ6IGZ1bmN0aW9uICgpIHsKICAgIGlmICggdHlwZW9mKCB3aW5kb3cuaW5uZXJIZWlnaHQgKSA9PSAnbnVtYmVyJyApCiAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJIZWlnaHQ7ICAvLyBOb24gSUUgYnJvd3NlcgoKICAgIGlmIChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCkKICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7ICAvLyBJRTYKCiAgICBpZiAoZG9jdW1lbnQuYm9keSAmJiBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodCkKICAgICAgcmV0dXJuIGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0OyAvLyBJRTQKICB9LAoKICBkb2N1bWVudF9oZWlnaHQ6IGZ1bmN0aW9uICgpIHsKICAgIHZhciBzaCwgb2g7CgogICAgc2ggPSBkb2N1bWVudC5ib2R5LnNjcm9sbEhlaWdodDsKICAgIG9oID0gZG9jdW1lbnQuYm9keS5vZmZzZXRIZWlnaHQ7CgogICAgaWYgKHNoICYmIG9oKQogICAgewogICAgICByZXR1cm4gKHNoID4gb2ggPyBzaCA6IG9oKTsKICAgIH0KCiAgICAvLyBubyBpZGVhIQogICAgcmV0dXJuIDA7CiAgfSwKCiAgc21hbGxlcjogZnVuY3Rpb24gKCkgewogICAgaWYgKHczY19zbGlkeS5zaXplX2luZGV4ID4gMCkKICAgIHsKICAgICAgLS13M2Nfc2xpZHkuc2l6ZV9pbmRleDsKICAgIH0KCiAgICB3M2Nfc2xpZHkudG9vbGJhci5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOwogICAgZG9jdW1lbnQuYm9keS5zdHlsZS5mb250U2l6ZSA9IHczY19zbGlkeS5zaXplc1t3M2Nfc2xpZHkuc2l6ZV9pbmRleF07CiAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgdzNjX3NsaWR5LmhpZGVfc2xpZGUoc2xpZGUpOwogICAgdzNjX3NsaWR5LnNob3dfc2xpZGUoc2xpZGUpOwogICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7dzNjX3NsaWR5LnNob3dfdG9vbGJhcigpOyB9LCA1MCk7CiAgfSwKCiAgYmlnZ2VyOiBmdW5jdGlvbiAoKSB7CiAgICBpZiAodzNjX3NsaWR5LnNpemVfaW5kZXggPCB3M2Nfc2xpZHkuc2l6ZXMubGVuZ3RoIC0gMSkKICAgIHsKICAgICAgKyt3M2Nfc2xpZHkuc2l6ZV9pbmRleDsKICAgIH0KCiAgICB3M2Nfc2xpZHkudG9vbGJhci5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOwogICAgZG9jdW1lbnQuYm9keS5zdHlsZS5mb250U2l6ZSA9IHczY19zbGlkeS5zaXplc1t3M2Nfc2xpZHkuc2l6ZV9pbmRleF07CiAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwogICAgdzNjX3NsaWR5LmhpZGVfc2xpZGUoc2xpZGUpOwogICAgdzNjX3NsaWR5LnNob3dfc2xpZGUoc2xpZGUpOwogICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7dzNjX3NsaWR5LnNob3dfdG9vbGJhcigpOyB9LCA1MCk7CiAgfSwKCiAgLy8gZW5hYmxlcyBjcm9zcyBicm93c2VyIHVzZSBvZiByZWxhdGl2ZSB3aWR0aC9oZWlnaHQKICAvLyBvbiBvYmplY3QgZWxlbWVudHMgZm9yIHVzZSB3aXRoIFNWRyBhbmQgRmxhc2ggbWVkaWEKICAvLyB3aXRoIHRoYW5rcyB0byBJdmFuIEhlcm1hbiBmb3IgdGhlIHN1Z2dlc3Rpb24KICBhZGp1c3Rfb2JqZWN0X2RpbWVuc2lvbnM6IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7CiAgICBmb3IoIHZhciBpID0gMDsgaSA8IHczY19zbGlkeS5vYmplY3RzLmxlbmd0aDsgaSsrICkKICAgIHsKICAgICAgdmFyIG9iaiA9IHRoaXMub2JqZWN0c1tpXTsKICAgICAgdmFyIG1pbWVUeXBlID0gb2JqLmdldEF0dHJpYnV0ZSgidHlwZSIpOwoKICAgICAgaWYgKG1pbWVUeXBlID09ICJpbWFnZS9zdmcreG1sIiB8fCBtaW1lVHlwZSA9PSAiYXBwbGljYXRpb24veC1zaG9ja3dhdmUtZmxhc2giKQogICAgICB7CiAgICAgICAgaWYgKCAhb2JqLmluaXRpYWxXaWR0aCApIAogICAgICAgICAgb2JqLmluaXRpYWxXaWR0aCA9IG9iai5nZXRBdHRyaWJ1dGUoIndpZHRoIik7CgogICAgICAgIGlmICggIW9iai5pbml0aWFsSGVpZ2h0ICkgCiAgICAgICAgICBvYmouaW5pdGlhbEhlaWdodCA9IG9iai5nZXRBdHRyaWJ1dGUoImhlaWdodCIpOwoKICAgICAgICBpZiAoIG9iai5pbml0aWFsV2lkdGggJiYgb2JqLmluaXRpYWxXaWR0aC5jaGFyQXQob2JqLmluaXRpYWxXaWR0aC5sZW5ndGgtMSkgPT0gIiUiICkKICAgICAgICB7CiAgICAgICAgICB2YXIgdyA9IHBhcnNlSW50KG9iai5pbml0aWFsV2lkdGguc2xpY2UoMCwgb2JqLmluaXRpYWxXaWR0aC5sZW5ndGgtMSkpOwogICAgICAgICAgdmFyIG5ld1cgPSB3aWR0aCAqICh3LzEwMC4wKTsKICAgICAgICAgIG9iai5zZXRBdHRyaWJ1dGUoIndpZHRoIixuZXdXKTsKICAgICAgICB9CgogICAgICAgIGlmICggb2JqLmluaXRpYWxIZWlnaHQgJiYKICAgICAgICAgICAgIG9iai5pbml0aWFsSGVpZ2h0LmNoYXJBdChvYmouaW5pdGlhbEhlaWdodC5sZW5ndGgtMSkgPT0gIiUiICkKICAgICAgICB7CiAgICAgICAgICB2YXIgaCA9IHBhcnNlSW50KG9iai5pbml0aWFsSGVpZ2h0LnNsaWNlKDAsIG9iai5pbml0aWFsSGVpZ2h0Lmxlbmd0aC0xKSk7CiAgICAgICAgICB2YXIgbmV3SCA9IGhlaWdodCAqIChoLzEwMC4wKTsKICAgICAgICAgIG9iai5zZXRBdHRyaWJ1dGUoImhlaWdodCIsIG5ld0gpOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0sCgogIC8vIG5lZWRlZCBmb3IgT3BlcmEgdG8gaW5oaWJpdCBkZWZhdWx0IGJlaGF2aW9yCiAgLy8gc2luY2UgT3BlcmEgZGVsaXZlcnMga2V5UHJlc3MgZXZlbiBpZiBrZXlEb3duCiAgLy8gd2FzIGNhbmNlbGxlZAogIGtleV9wcmVzczogZnVuY3Rpb24gKGV2ZW50KSB7CiAgICBpZiAoIWV2ZW50KQogICAgICBldmVudCA9IHdpbmRvdy5ldmVudDsKCiAgICBpZiAoIXczY19zbGlkeS5rZXlfd2FudGVkKQogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CgogICAgcmV0dXJuIHRydWU7CiAgfSwKCiAgLy8gIFNlZSBlLmcuIGh0dHA6Ly93d3cucXVpcmtzbW9kZS5vcmcvanMvZXZlbnRzL2tleXMuaHRtbCBmb3Iga2V5Y29kZXMKICBrZXlfZG93bjogZnVuY3Rpb24gKGV2ZW50KSB7CiAgICB2YXIga2V5LCB0YXJnZXQsIHRhZzsKCiAgICB3M2Nfc2xpZHkua2V5X3dhbnRlZCA9IHRydWU7CgogICAgaWYgKCFldmVudCkKICAgICAgZXZlbnQgPSB3aW5kb3cuZXZlbnQ7CgogICAgLy8ga2x1ZGdlIGFyb3VuZCBOUy9JRSBkaWZmZXJlbmNlcyAKICAgIGlmICh3aW5kb3cuZXZlbnQpCiAgICB7CiAgICAgIGtleSA9IHdpbmRvdy5ldmVudC5rZXlDb2RlOwogICAgICB0YXJnZXQgPSB3aW5kb3cuZXZlbnQuc3JjRWxlbWVudDsKICAgIH0KICAgIGVsc2UgaWYgKGV2ZW50LndoaWNoKQogICAgewogICAgICBrZXkgPSBldmVudC53aGljaDsKICAgICAgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0OwogICAgfQogICAgZWxzZQogICAgICByZXR1cm4gdHJ1ZTsgLy8gWWlrZXMhIHVua25vd24gYnJvd3NlcgoKICAgIC8vIGlnbm9yZSBldmVudCBpZiBrZXkgdmFsdWUgaXMgemVybwogICAgLy8gYXMgZm9yIGFsdCBvbiBPcGVyYSBhbmQgS29ucXVlcm9yCiAgICBpZiAoIWtleSkKICAgICAgIHJldHVybiB0cnVlOwoKICAgIC8vIGF2b2lkIGludGVyZmVyaW5nIHdpdGgga2V5c3Ryb2tlCiAgICAvLyBiZWhhdmlvciBmb3Igbm9uLXNsaWR5IGNocm9tZSBlbGVtZW50cwogICAgaWYgKCF3M2Nfc2xpZHkuc2xpZHlfY2hyb21lKHRhcmdldCkgJiYKICAgICAgICB3M2Nfc2xpZHkuc3BlY2lhbF9lbGVtZW50KHRhcmdldCkpCiAgICAgIHJldHVybiB0cnVlOwoKICAgIC8vIGNoZWNrIGZvciBjb25jdXJyZW50IGNvbnRyb2wvY29tbWFuZC9hbHQga2V5CiAgICAvLyBidXQgYXJlIHRoZXNlIG9ubHkgcHJlc2VudCBvbiBtb3VzZSBldmVudHM/CgogICAgaWYgKGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQuYWx0S2V5IHx8IGV2ZW50Lm1ldGFLZXkpCiAgICAgICByZXR1cm4gdHJ1ZTsKCiAgICAvLyBkaXNtaXNzIHRhYmxlIG9mIGNvbnRlbnRzIGlmIHZpc2libGUKICAgIGlmICh3M2Nfc2xpZHkuaXNfc2hvd25fdG9jKCkgJiYga2V5ICE9IDkgJiYga2V5ICE9IDE2ICYmIGtleSAhPSAzOCAmJiBrZXkgIT0gNDApCiAgICB7CiAgICAgIHczY19zbGlkeS5oaWRlX3RhYmxlX29mX2NvbnRlbnRzKHRydWUpOwoKICAgICAgaWYgKGtleSA9PSAyNyB8fCBrZXkgPT0gODQgfHwga2V5ID09IDY3KQogICAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KCiAgICBpZiAoa2V5ID09IDM0KSAvLyBQYWdlIERvd24KICAgIHsKICAgICAgaWYgKHczY19zbGlkeS52aWV3X2FsbCkKICAgICAgICByZXR1cm4gdHJ1ZTsKCiAgICAgIHczY19zbGlkeS5uZXh0X3NsaWRlKGZhbHNlKTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDMzKSAvLyBQYWdlIFVwCiAgICB7CiAgICAgIGlmICh3M2Nfc2xpZHkudmlld19hbGwpCiAgICAgICAgcmV0dXJuIHRydWU7CgogICAgICB3M2Nfc2xpZHkucHJldmlvdXNfc2xpZGUoZmFsc2UpOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CiAgICBlbHNlIGlmIChrZXkgPT0gMzIpIC8vIHNwYWNlIGJhcgogICAgewogICAgICB3M2Nfc2xpZHkubmV4dF9zbGlkZSh0cnVlKTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDM3KSAvLyBMZWZ0IGFycm93CiAgICB7CiAgICAgIHczY19zbGlkeS5wcmV2aW91c19zbGlkZSghZXZlbnQuc2hpZnRLZXkpOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CiAgICBlbHNlIGlmIChrZXkgPT0gMzYpIC8vIEhvbWUKICAgIHsKICAgICAgdzNjX3NsaWR5LmZpcnN0X3NsaWRlKCk7CiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KICAgIGVsc2UgaWYgKGtleSA9PSAzNSkgLy8gRW5kCiAgICB7CiAgICAgIHczY19zbGlkeS5sYXN0X3NsaWRlKCk7CiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KICAgIGVsc2UgaWYgKGtleSA9PSAzOSkgLy8gUmlnaHQgYXJyb3cKICAgIHsKICAgICAgdzNjX3NsaWR5Lm5leHRfc2xpZGUoIWV2ZW50LnNoaWZ0S2V5KTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDEzKSAvLyBFbnRlcgogICAgewogICAgICBpZiAodzNjX3NsaWR5Lm91dGxpbmUpCiAgICAgIHsKICAgICAgICBpZiAodzNjX3NsaWR5Lm91dGxpbmUudmlzaWJsZSkKICAgICAgICAgIHczY19zbGlkeS5mb2xkKHczY19zbGlkeS5vdXRsaW5lKTsKICAgICAgICBlbHNlCiAgICAgICAgICB3M2Nfc2xpZHkudW5mb2xkKHczY19zbGlkeS5vdXRsaW5lKTsKICAgICAgICAgIAogICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgICB9CiAgICB9CiAgICBlbHNlIGlmIChrZXkgPT0gMTg4KSAgLy8gPCBmb3Igc21hbGxlciBmb250cwogICAgewogICAgICB3M2Nfc2xpZHkuc21hbGxlcigpOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CiAgICBlbHNlIGlmIChrZXkgPT0gMTkwKSAgLy8gPiBmb3IgbGFyZ2VyIGZvbnRzCiAgICB7CiAgICAgIHczY19zbGlkeS5iaWdnZXIoKTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDE4OSB8fCBrZXkgPT0gMTA5KSAgLy8gLSBmb3Igc21hbGxlciBmb250cwogICAgewogICAgICB3M2Nfc2xpZHkuc21hbGxlcigpOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CiAgICBlbHNlIGlmIChrZXkgPT0gMTg3IHx8IGtleSA9PSAxOTEgfHwga2V5ID09IDEwNykgIC8vID0gKyAgZm9yIGxhcmdlciBmb250cwogICAgewogICAgICB3M2Nfc2xpZHkuYmlnZ2VyKCk7CiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KICAgIGVsc2UgaWYgKGtleSA9PSA4MykgIC8vIFMgZm9yIHNtYWxsZXIgZm9udHMKICAgIHsKICAgICAgdzNjX3NsaWR5LnNtYWxsZXIoKTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDY2KSAgLy8gQiBmb3IgbGFyZ2VyIGZvbnRzCiAgICB7CiAgICAgIHczY19zbGlkeS5iaWdnZXIoKTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDkwKSAgLy8gWiBmb3IgbGFzdCBzbGlkZQogICAgewogICAgICB3M2Nfc2xpZHkubGFzdF9zbGlkZSgpOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CiAgICBlbHNlIGlmIChrZXkgPT0gNzApICAvLyBGIGZvciB0b2dnbGUgdG9vbGJhcgogICAgewogICAgICB3M2Nfc2xpZHkudG9nZ2xlX3Rvb2xiYXIoKTsKICAgICAgcmV0dXJuIHczY19zbGlkeS5jYW5jZWwoZXZlbnQpOwogICAgfQogICAgZWxzZSBpZiAoa2V5ID09IDY1KSAgLy8gQSBmb3IgdG9nZ2xlIHZpZXcgc2luZ2xlL2FsbCBzbGlkZXMKICAgIHsKICAgICAgdzNjX3NsaWR5LnRvZ2dsZV92aWV3KCk7CiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KICAgIGVsc2UgaWYgKGtleSA9PSA3NSkgIC8vIHRvZ2dsZSBhY3Rpb24gb2YgbGVmdCBjbGljayBmb3IgbmV4dCBwYWdlCiAgICB7CiAgICAgIHczY19zbGlkeS5tb3VzZV9jbGlja19lbmFibGVkID0gIXczY19zbGlkeS5tb3VzZV9jbGlja19lbmFibGVkOwogICAgICB2YXIgYWxlcnRfbXNnID0gKHczY19zbGlkeS5tb3VzZV9jbGlja19lbmFibGVkID8KICAgICAgICAgICAgICAgICJlbmFibGVkIiA6ICJkaXNhYmxlZCIpICsgICIgbW91c2UgY2xpY2sgYWR2YW5jZSI7CgogICAgICBhbGVydCh3M2Nfc2xpZHkubG9jYWxpemUoYWxlcnRfbXNnKSk7CiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KICAgIGVsc2UgaWYgKGtleSA9PSA4NCB8fCBrZXkgPT0gNjcpICAvLyBUIG9yIEMgZm9yIHRhYmxlIG9mIGNvbnRlbnRzCiAgICB7CiAgICAgIGlmICh3M2Nfc2xpZHkudG9jKQogICAgICAgIHczY19zbGlkeS50b2dnbGVfdGFibGVfb2ZfY29udGVudHMoKTsKCiAgICAgIHJldHVybiB3M2Nfc2xpZHkuY2FuY2VsKGV2ZW50KTsKICAgIH0KICAgIGVsc2UgaWYgKGtleSA9PSA3MikgLy8gSCBmb3IgaGVscAogICAgewogICAgICB3aW5kb3cubG9jYXRpb24gPSB3M2Nfc2xpZHkuaGVscF9wYWdlOwogICAgICByZXR1cm4gdzNjX3NsaWR5LmNhbmNlbChldmVudCk7CiAgICB9CiAgICAvL2Vsc2UgYWxlcnQoImtleSBjb2RlIGlzICIrIGtleSk7CgogICAgcmV0dXJuIHRydWU7CiAgfSwKCiAgLy8gc2FmZSBmb3IgYm90aCB0ZXh0L2h0bWwgYW5kIGFwcGxpY2F0aW9uL3hodG1sK3htbAogIGNyZWF0ZV9lbGVtZW50OiBmdW5jdGlvbiAobmFtZSkgewogICAgaWYgKHRoaXMueGh0bWwgJiYgKHR5cGVvZiBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMgIT0gJ3VuZGVmaW5lZCcpKQogICAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiwgbmFtZSkKCiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChuYW1lKTsKICB9LAoKICBnZXRfZWxlbWVudF9zdHlsZTogZnVuY3Rpb24gKGVsZW0sIElFU3R5bGVQcm9wLCBDU1NTdHlsZVByb3ApIHsKICAgIGlmIChlbGVtLmN1cnJlbnRTdHlsZSkKICAgIHsKICAgICAgcmV0dXJuIGVsZW0uY3VycmVudFN0eWxlW0lFU3R5bGVQcm9wXTsKICAgIH0KICAgIGVsc2UgaWYgKHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKQogICAgewogICAgICB2YXIgY29tcFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbSwgIiIpOwogICAgICByZXR1cm4gY29tcFN0eWxlLmdldFByb3BlcnR5VmFsdWUoQ1NTU3R5bGVQcm9wKTsKICAgIH0KICAgIHJldHVybiAiIjsKICB9LAoKICAvLyB0aGUgc3RyaW5nIHN0ciBpcyBhIHdoaXRlc3BhY2Ugc2VwYXJhdGVkIGxpc3Qgb2YgdG9rZW5zCiAgLy8gdGVzdCBpZiBzdHIgY29udGFpbnMgYSBwYXJ0aWN1bGFyIHRva2VuLCBlLmcuICJzbGlkZSIKICBoYXNfdG9rZW46IGZ1bmN0aW9uIChzdHIsIHRva2VuKSB7CiAgICBpZiAoc3RyKQogICAgewogICAgICAvLyBkZWZpbmUgcGF0dGVybiBhcyByZWd1bGFyIGV4cHJlc3Npb24KICAgICAgdmFyIHBhdHRlcm4gPSAvXHcrL2c7CgogICAgICAvLyBjaGVjayBmb3IgbWF0Y2hlcwogICAgICAvLyBwbGFjZSByZXN1bHQgaW4gYXJyYXkKICAgICAgdmFyIHJlc3VsdCA9IHN0ci5tYXRjaChwYXR0ZXJuKTsKCiAgICAgIC8vIG5vdyBjaGVjayBpZiBkZXNpcmVkIHRva2VuIGlzIHByZXNlbnQKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN1bHQubGVuZ3RoOyBpKyspCiAgICAgIHsKICAgICAgICBpZiAocmVzdWx0W2ldID09IHRva2VuKQogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfSwKCiAgZ2V0X2NsYXNzX2xpc3Q6IGZ1bmN0aW9uIChlbGVtZW50KSB7CiAgICBpZiAodHlwZW9mIGVsZW1lbnQuY2xhc3NOYW1lICE9ICd1bmRlZmluZWQnKQogICAgICByZXR1cm4gZWxlbWVudC5jbGFzc05hbWU7CgogICAgcmV0dXJuIGVsZW1lbnQuZ2V0QXR0cmlidXRlKCJjbGFzcyIpOwogIH0sCgogIGhhc19jbGFzczogZnVuY3Rpb24gKGVsZW1lbnQsIG5hbWUpIHsKICAgIGlmIChlbGVtZW50Lm5vZGVUeXBlICE9IDEpCiAgICAgIHJldHVybiBmYWxzZTsKCiAgICB2YXIgcmVnZXhwID0gbmV3IFJlZ0V4cCgiKF58ICkiICsgbmFtZSArICJcVyoiKTsKCiAgICBpZiAodHlwZW9mIGVsZW1lbnQuY2xhc3NOYW1lICE9ICd1bmRlZmluZWQnKQogICAgICByZXR1cm4gcmVnZXhwLnRlc3QoZWxlbWVudC5jbGFzc05hbWUpOwoKICAgIHJldHVybiByZWdleHAudGVzdChlbGVtZW50LmdldEF0dHJpYnV0ZSgiY2xhc3MiKSk7CiAgfSwKCiAgcmVtb3ZlX2NsYXNzOiBmdW5jdGlvbiAoZWxlbWVudCwgbmFtZSkgewogICAgdmFyIHJlZ2V4cCA9IG5ldyBSZWdFeHAoIihefCApIiArIG5hbWUgKyAiXFcqIik7CiAgICB2YXIgY2xzdmFsID0gIiI7CgogICAgaWYgKHR5cGVvZiBlbGVtZW50LmNsYXNzTmFtZSAhPSAndW5kZWZpbmVkJykKICAgIHsKICAgICAgY2xzdmFsID0gZWxlbWVudC5jbGFzc05hbWU7CgogICAgICBpZiAoY2xzdmFsKQogICAgICB7CiAgICAgICAgY2xzdmFsID0gY2xzdmFsLnJlcGxhY2UocmVnZXhwLCAiIik7CiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSBjbHN2YWw7CiAgICAgIH0KICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgY2xzdmFsID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoImNsYXNzIik7CgogICAgICBpZiAoY2xzdmFsKQogICAgICB7CiAgICAgICAgY2xzdmFsID0gY2xzdmFsLnJlcGxhY2UocmVnZXhwLCAiIik7CiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgY2xzdmFsKTsKICAgICAgfQogICAgfQogIH0sCgogIGFkZF9jbGFzczogZnVuY3Rpb24gKGVsZW1lbnQsIG5hbWUpIHsKICAgIGlmICghdGhpcy5oYXNfY2xhc3MoZWxlbWVudCwgbmFtZSkpCiAgICB7CiAgICAgIGlmICh0eXBlb2YgZWxlbWVudC5jbGFzc05hbWUgIT0gJ3VuZGVmaW5lZCcpCiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgKz0gIiAiICsgbmFtZTsKICAgICAgZWxzZQogICAgICB7CiAgICAgICAgdmFyIGNsc3ZhbCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCJjbGFzcyIpOwogICAgICAgIGNsc3ZhbCA9IGNsc3ZhbCA/IGNsc3ZhbCArICIgIiArIG5hbWUgOiBuYW1lOwogICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJjbGFzcyIsIGNsc3ZhbCk7CiAgICAgIH0KICAgIH0KICB9LAoKICAvLyBIVE1MIGVsZW1lbnRzIHRoYXQgY2FuIGJlIHVzZWQgd2l0aCBjbGFzcz0iaW5jcmVtZW50YWwiCiAgLy8gbm90ZSB0aGF0IHlvdSBjYW4gYWxzbyBwdXQgdGhlIGNsYXNzIG9uIGNvbnRhaW5lcnMgbGlrZQogIC8vIHVwLCBvbCwgZGwsIGFuZCBkaXYgdG8gbWFrZSB0aGVpciBjb250ZW50cyBhcHBlYXIKICAvLyBpbmNyZW1lbnRhbGx5LiBVcHBlciBjYXNlIGlzIHVzZWQgc2luY2UgdGhpcyBpcyB3aGF0CiAgLy8gYnJvd3NlcnMgcmVwb3J0IGZvciBIVE1MIG5vZGUgbmFtZXMgKHRleHQvaHRtbCkuCiAgaW5jcmVtZW50YWxfZWxlbWVudHM6IG51bGwsCiAgb2theV9mb3JfaW5jcmVtZW50YWw6IGZ1bmN0aW9uIChuYW1lKSB7CiAgICBpZiAoIXRoaXMuaW5jcmVtZW50YWxfZWxlbWVudHMpCiAgICB7CiAgICAgIHZhciBpbmNsaXN0ID0gbmV3IEFycmF5KCk7CiAgICAgIGluY2xpc3RbInAiXSA9IHRydWU7CiAgICAgIGluY2xpc3RbInByZSJdID0gdHJ1ZTsKICAgICAgaW5jbGlzdFsibGkiXSA9IHRydWU7CiAgICAgIGluY2xpc3RbImJsb2NrcXVvdGUiXSA9IHRydWU7CiAgICAgIGluY2xpc3RbImR0Il0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJkZCJdID0gdHJ1ZTsKICAgICAgaW5jbGlzdFsiaDIiXSA9IHRydWU7CiAgICAgIGluY2xpc3RbImgzIl0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJoNCJdID0gdHJ1ZTsKICAgICAgaW5jbGlzdFsiaDUiXSA9IHRydWU7CiAgICAgIGluY2xpc3RbImg2Il0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJzcGFuIl0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJhZGRyZXNzIl0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJ0YWJsZSJdID0gdHJ1ZTsKICAgICAgaW5jbGlzdFsidHIiXSA9IHRydWU7CiAgICAgIGluY2xpc3RbInRoIl0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJ0ZCJdID0gdHJ1ZTsKICAgICAgaW5jbGlzdFsiaW1nIl0gPSB0cnVlOwogICAgICBpbmNsaXN0WyJvYmplY3QiXSA9IHRydWU7CiAgICAgIHRoaXMuaW5jcmVtZW50YWxfZWxlbWVudHMgPSBpbmNsaXN0OwogICAgfQogICAgcmV0dXJuIHRoaXMuaW5jcmVtZW50YWxfZWxlbWVudHNbbmFtZS50b0xvd2VyQ2FzZSgpXTsKICB9LAoKICBuZXh0X2luY3JlbWVudGFsX2l0ZW06IGZ1bmN0aW9uIChub2RlKSB7CiAgICB2YXIgYnIgPSB0aGlzLmlzX3hodG1sID8gImJyIiA6ICJCUiI7CiAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwoKICAgIGZvciAoOzspCiAgICB7CiAgICAgIG5vZGUgPSB3M2Nfc2xpZHkubmV4dF9ub2RlKHNsaWRlLCBub2RlKTsKCiAgICAgIGlmIChub2RlID09IG51bGwgfHwgbm9kZS5wYXJlbnROb2RlID09IG51bGwpCiAgICAgICAgYnJlYWs7CgogICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PSAxKSAgLy8gRUxFTUVOVAogICAgICB7CiAgICAgICAgaWYgKG5vZGUubm9kZU5hbWUgPT0gYnIpCiAgICAgICAgICBjb250aW51ZTsKCiAgICAgICAgaWYgKHczY19zbGlkeS5oYXNfY2xhc3Mobm9kZSwgImluY3JlbWVudGFsIikKICAgICAgICAgICAgICYmIHczY19zbGlkeS5va2F5X2Zvcl9pbmNyZW1lbnRhbChub2RlLm5vZGVOYW1lKSkKICAgICAgICAgIHJldHVybiBub2RlOwoKICAgICAgICBpZiAodzNjX3NsaWR5Lmhhc19jbGFzcyhub2RlLnBhcmVudE5vZGUsICJpbmNyZW1lbnRhbCIpCiAgICAgICAgICAgICAmJiAhdzNjX3NsaWR5Lmhhc19jbGFzcyhub2RlLCAibm9uLWluY3JlbWVudGFsIikpCiAgICAgICAgICByZXR1cm4gbm9kZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBub2RlOwogIH0sCgogIHByZXZpb3VzX2luY3JlbWVudGFsX2l0ZW06IGZ1bmN0aW9uIChub2RlKSB7CiAgICB2YXIgYnIgPSB0aGlzLmlzX3hodG1sID8gImJyIiA6ICJCUiI7CiAgICB2YXIgc2xpZGUgPSB3M2Nfc2xpZHkuc2xpZGVzW3czY19zbGlkeS5zbGlkZV9udW1iZXJdOwoKICAgIGZvciAoOzspCiAgICB7CiAgICAgIG5vZGUgPSB3M2Nfc2xpZHkucHJldmlvdXNfbm9kZShzbGlkZSwgbm9kZSk7CgogICAgICBpZiAobm9kZSA9PSBudWxsIHx8IG5vZGUucGFyZW50Tm9kZSA9PSBudWxsKQogICAgICAgIGJyZWFrOwoKICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT0gMSkKICAgICAgewogICAgICAgIGlmIChub2RlLm5vZGVOYW1lID09IGJyKQogICAgICAgICAgY29udGludWU7CgogICAgICAgIGlmICh3M2Nfc2xpZHkuaGFzX2NsYXNzKG5vZGUsICJpbmNyZW1lbnRhbCIpCiAgICAgICAgICAgICAmJiB3M2Nfc2xpZHkub2theV9mb3JfaW5jcmVtZW50YWwobm9kZS5ub2RlTmFtZSkpCiAgICAgICAgICByZXR1cm4gbm9kZTsKCiAgICAgICAgaWYgKHczY19zbGlkeS5oYXNfY2xhc3Mobm9kZS5wYXJlbnROb2RlLCAiaW5jcmVtZW50YWwiKQogICAgICAgICAgICAgJiYgIXczY19zbGlkeS5oYXNfY2xhc3Mobm9kZSwgIm5vbi1pbmNyZW1lbnRhbCIpKQogICAgICAgICAgcmV0dXJuIG5vZGU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gbm9kZTsKICB9LAoKICAvLyBzZXQgdmlzaWJpbGl0eSBmb3IgYWxsIGVsZW1lbnRzIG9uIGN1cnJlbnQgc2xpZGUgd2l0aAogIC8vIGEgcGFyZW50IGVsZW1lbnQgd2l0aCBhdHRyaWJ1dGUgY2xhc3M9ImluY3JlbWVudGFsIgogIHNldF92aXNpYmlsaXR5X2FsbF9pbmNyZW1lbnRhbDogZnVuY3Rpb24gKHZhbHVlKSB7CiAgICB2YXIgbm9kZSA9IHRoaXMubmV4dF9pbmNyZW1lbnRhbF9pdGVtKG51bGwpOwoKICAgIGlmICh2YWx1ZSA9PSAiaGlkZGVuIikKICAgIHsKICAgICAgd2hpbGUgKG5vZGUpCiAgICAgIHsKICAgICAgICB3M2Nfc2xpZHkuYWRkX2NsYXNzKG5vZGUsICJpbnZpc2libGUiKTsKICAgICAgICBub2RlID0gdzNjX3NsaWR5Lm5leHRfaW5jcmVtZW50YWxfaXRlbShub2RlKTsKICAgICAgfQogICAgfQogICAgZWxzZSAvLyB2YWx1ZSA9PSAidmlzaWJsZSIKICAgIHsKICAgICAgd2hpbGUgKG5vZGUpCiAgICAgIHsKICAgICAgICB3M2Nfc2xpZHkucmVtb3ZlX2NsYXNzKG5vZGUsICJpbnZpc2libGUiKTsKICAgICAgICBub2RlID0gdzNjX3NsaWR5Lm5leHRfaW5jcmVtZW50YWxfaXRlbShub2RlKTsKICAgICAgfQogICAgfQogIH0sCgogIC8vIHJldmVhbCB0aGUgbmV4dCBoaWRkZW4gaXRlbSBvbiB0aGUgc2xpZGUKICAvLyBub2RlIGlzIG51bGwgb3IgdGhlIG5vZGUgdGhhdCB3YXMgbGFzdCByZXZlYWxlZAogIHJldmVhbF9uZXh0X2l0ZW06IGZ1bmN0aW9uIChub2RlKSB7CiAgICBub2RlID0gdzNjX3NsaWR5Lm5leHRfaW5jcmVtZW50YWxfaXRlbShub2RlKTsKCiAgICBpZiAobm9kZSAmJiBub2RlLm5vZGVUeXBlID09IDEpICAvLyBhbiBlbGVtZW50CiAgICAgIHczY19zbGlkeS5yZW1vdmVfY2xhc3Mobm9kZSwgImludmlzaWJsZSIpOwoKICAgIHJldHVybiBub2RlOwogIH0sCgogIC8vIGV4YWN0IGludmVyc2Ugb2YgcmV2ZWFsTmV4dEl0ZW0obm9kZSkKICBoaWRlX3ByZXZpb3VzX2l0ZW06IGZ1bmN0aW9uIChub2RlKSB7CiAgICBpZiAobm9kZSAmJiBub2RlLm5vZGVUeXBlID09IDEpICAvLyBhbiBlbGVtZW50CiAgICAgIHczY19zbGlkeS5hZGRfY2xhc3Mobm9kZSwgImludmlzaWJsZSIpOwoKICAgIHJldHVybiB0aGlzLnByZXZpb3VzX2luY3JlbWVudGFsX2l0ZW0obm9kZSk7CiAgfSwKCiAgLy8gbGVmdCB0byByaWdodCB0cmF2ZXJzYWwgb2Ygcm9vdCdzIGNvbnRlbnQKICBuZXh0X25vZGU6IGZ1bmN0aW9uIChyb290LCBub2RlKSB7CiAgICBpZiAobm9kZSA9PSBudWxsKQogICAgICByZXR1cm4gcm9vdC5maXJzdENoaWxkOwoKICAgIGlmIChub2RlLmZpcnN0Q2hpbGQpCiAgICAgIHJldHVybiBub2RlLmZpcnN0Q2hpbGQ7CgogICAgaWYgKG5vZGUubmV4dFNpYmxpbmcpCiAgICAgIHJldHVybiBub2RlLm5leHRTaWJsaW5nOwoKICAgIGZvciAoOzspCiAgICB7CiAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7CgogICAgICBpZiAoIW5vZGUgfHwgbm9kZSA9PSByb290KQogICAgICAgIGJyZWFrOwoKICAgICAgaWYgKG5vZGUgJiYgbm9kZS5uZXh0U2libGluZykKICAgICAgICByZXR1cm4gbm9kZS5uZXh0U2libGluZzsKICAgIH0KCiAgICByZXR1cm4gbnVsbDsKICB9LAoKICAvLyByaWdodCB0byBsZWZ0IHRyYXZlcnNhbCBvZiByb290J3MgY29udGVudAogIHByZXZpb3VzX25vZGU6IGZ1bmN0aW9uIChyb290LCBub2RlKSB7CiAgICBpZiAobm9kZSA9PSBudWxsKQogICAgewogICAgICBub2RlID0gcm9vdC5sYXN0Q2hpbGQ7CgogICAgICBpZiAobm9kZSkKICAgICAgewogICAgICAgIHdoaWxlIChub2RlLmxhc3RDaGlsZCkKICAgICAgICAgIG5vZGUgPSBub2RlLmxhc3RDaGlsZDsKICAgICAgfQoKICAgICAgcmV0dXJuIG5vZGU7CiAgICB9CgogICAgaWYgKG5vZGUucHJldmlvdXNTaWJsaW5nKQogICAgewogICAgICBub2RlID0gbm9kZS5wcmV2aW91c1NpYmxpbmc7CgogICAgICB3aGlsZSAobm9kZS5sYXN0Q2hpbGQpCiAgICAgICAgbm9kZSA9IG5vZGUubGFzdENoaWxkOwoKICAgICAgcmV0dXJuIG5vZGU7CiAgICB9CgogICAgaWYgKG5vZGUucGFyZW50Tm9kZSAhPSByb290KQogICAgICByZXR1cm4gbm9kZS5wYXJlbnROb2RlOwoKICAgIHJldHVybiBudWxsOwogIH0sCgogIHByZXZpb3VzX3NpYmxpbmdfZWxlbWVudDogZnVuY3Rpb24gKGVsKSB7CiAgICBlbCA9IGVsLnByZXZpb3VzU2libGluZzsKCiAgICB3aGlsZSAoZWwgJiYgZWwubm9kZVR5cGUgIT0gMSkKICAgICAgZWwgPSBlbC5wcmV2aW91c1NpYmxpbmc7CgogICAgcmV0dXJuIGVsOwogIH0sCgogIG5leHRfc2libGluZ19lbGVtZW50OiBmdW5jdGlvbiAoZWwpIHsKICAgIGVsID0gZWwubmV4dFNpYmxpbmc7CgogICAgd2hpbGUgKGVsICYmIGVsLm5vZGVUeXBlICE9IDEpCiAgICAgIGVsID0gZWwubmV4dFNpYmxpbmc7CgogICAgcmV0dXJuIGVsOwogIH0sCgogIGZpcnN0X2NoaWxkX2VsZW1lbnQ6IGZ1bmN0aW9uIChlbCkgewogICAgdmFyIG5vZGU7CgogICAgZm9yIChub2RlID0gZWwuZmlyc3RDaGlsZDsgbm9kZTsgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmcpCiAgICB7CiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09IDEpCiAgICAgICAgYnJlYWs7CiAgICB9CgogICAgcmV0dXJuIG5vZGU7CiAgfSwKCiAgZmlyc3RfdGFnOiBmdW5jdGlvbiAoZWxlbWVudCwgdGFnKSB7CiAgICB2YXIgbm9kZTsKCiAgICBpZiAoIXRoaXMuaXNfeGh0bWwpCiAgICAgIHRhZyA9IHRhZy50b1VwcGVyQ2FzZSgpOwoKICAgIGZvciAobm9kZSA9IGVsZW1lbnQuZmlyc3RDaGlsZDsgbm9kZTsgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmcpCiAgICB7CiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09IDEgJiYgbm9kZS5ub2RlTmFtZSA9PSB0YWcpCiAgICAgICAgYnJlYWs7CiAgICB9CgogICAgcmV0dXJuIG5vZGU7CiAgfSwKCiAgaGlkZV9zZWxlY3Rpb246IGZ1bmN0aW9uICgpIHsKICAgIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSAvLyBGaXJlZm94LCBDaHJvbWl1bSwgU2FmYXJpLCBPcGVyYQogICAgewogICAgICB2YXIgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpOwoKICAgICAgaWYgKHNlbGVjdGlvbi5yYW5nZUNvdW50ID4gMCkKICAgICAgewogICAgICAgIHZhciByYW5nZSA9IHNlbGVjdGlvbi5nZXRSYW5nZUF0KDApOwogICAgICAgIHJhbmdlLmNvbGxhcHNlIChmYWxzZSk7CiAgICAgIH0KICAgIH0KICAgIGVsc2UgLy8gSW50ZXJuZXQgRXhwbG9yZXIKICAgIHsKICAgICAgdmFyIHRleHRSYW5nZSA9IGRvY3VtZW50LnNlbGVjdGlvbi5jcmVhdGVSYW5nZSAoKTsKICAgICAgdGV4dFJhbmdlLmNvbGxhcHNlIChmYWxzZSk7CiAgICB9CiAgfSwKCiAgZ2V0X3NlbGVjdGVkX3RleHQ6IGZ1bmN0aW9uICgpIHsKICAgIHRyeQogICAgewogICAgICBpZiAod2luZG93LmdldFNlbGVjdGlvbikKICAgICAgICByZXR1cm4gd2luZG93LmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCk7CgogICAgICBpZiAoZG9jdW1lbnQuZ2V0U2VsZWN0aW9uKQogICAgICAgIHJldHVybiBkb2N1bWVudC5nZXRTZWxlY3Rpb24oKS50b1N0cmluZygpOwoKICAgICAgaWYgKGRvY3VtZW50LnNlbGVjdGlvbikKICAgICAgICByZXR1cm4gZG9jdW1lbnQuc2VsZWN0aW9uLmNyZWF0ZVJhbmdlKCkudGV4dDsKICAgIH0KICAgIGNhdGNoIChlKQogICAgewogICAgfQoKICAgIHJldHVybiAiIjsKICB9LAoKICAvLyBtYWtlIG5vdGUgb2YgbGVuZ3RoIG9mIHNlbGVjdGVkIHRleHQKICAvLyBhcyB0aGlzIGV2YWx1YXRlcyB0byB6ZXJvIGluIGNsaWNrIGV2ZW50CiAgbW91c2VfYnV0dG9uX3VwOiBmdW5jdGlvbiAoZSkgewogICAgdzNjX3NsaWR5LnNlbGVjdGVkX3RleHRfbGVuID0gdzNjX3NsaWR5LmdldF9zZWxlY3RlZF90ZXh0KCkubGVuZ3RoOwogIH0sCgogIG1vdXNlX2J1dHRvbl9kb3duOiBmdW5jdGlvbiAoZSkgewogICAgdzNjX3NsaWR5LnNlbGVjdGVkX3RleHRfbGVuID0gdzNjX3NsaWR5LmdldF9zZWxlY3RlZF90ZXh0KCkubGVuZ3RoOwogICAgdzNjX3NsaWR5Lm1vdXNlX3ggPSBlLmNsaWVudFg7CiAgICB3M2Nfc2xpZHkubW91c2VfeSA9IGUuY2xpZW50WTsKICB9LAoKICAvLyByaWdodCBtb3VzZSBidXR0b24gY2xpY2sgaXMgcmVzZXJ2ZWQgZm9yIGNvbnRleHQgbWVudXMKICAvLyBpdCBpcyBtb3JlIHJlbGlhYmxlIHRvIGRldGVjdCByaWdodGNsaWNrIHRoYW4gbGVmdGNsaWNrCiAgbW91c2VfYnV0dG9uX2NsaWNrOiBmdW5jdGlvbiAoZSkgewogICAgaWYgKCFlKQogICAgICB2YXIgZSA9IHdpbmRvdy5ldmVudDsKCiAgICBpZiAoTWF0aC5hYnMoZS5jbGllbnRYIC13M2Nfc2xpZHkubW91c2VfeCkgKwogICAgICAgIE1hdGguYWJzKGUuY2xpZW50WSAtdzNjX3NsaWR5Lm1vdXNlX3kpID4gMTApCiAgICAgIHJldHVybiB0cnVlOwoKICAgIGlmICh3M2Nfc2xpZHkuc2VsZWN0ZWRfdGV4dF9sZW4gPiAwKQogICAgICByZXR1cm4gdHJ1ZTsKCiAgICB2YXIgcmlnaHRjbGljayA9IGZhbHNlOwogICAgdmFyIGxlZnRjbGljayA9IGZhbHNlOwogICAgdmFyIG1pZGRsZWNsaWNrID0gZmFsc2U7CiAgICB2YXIgdGFyZ2V0OwoKICAgIGlmICghZSkKICAgICAgdmFyIGUgPSB3aW5kb3cuZXZlbnQ7CgogICAgaWYgKGUudGFyZ2V0KQogICAgICB0YXJnZXQgPSBlLnRhcmdldDsKICAgIGVsc2UgaWYgKGUuc3JjRWxlbWVudCkKICAgICAgdGFyZ2V0ID0gZS5zcmNFbGVtZW50OwoKICAgIC8vIHdvcmsgYXJvdW5kIFNhZmFyaSBidWcKICAgIGlmICh0YXJnZXQubm9kZVR5cGUgPT0gMykKICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnBhcmVudE5vZGU7CgogICAgaWYgKGUud2hpY2gpIC8vIGFsbCBicm93c2VycyBleGNlcHQgSUUKICAgIHsKICAgICAgbGVmdGNsaWNrID0gKGUud2hpY2ggPT0gMSk7CiAgICAgIG1pZGRsZWNsaWNrID0gKGUud2hpY2ggPT0gMik7CiAgICAgIHJpZ2h0Y2xpY2sgPSAoZS53aGljaCA9PSAzKTsKICAgIH0KICAgIGVsc2UgaWYgKGUuYnV0dG9uKQogICAgewogICAgICAvLyBLb25xdWVyb3IgZ2l2ZXMgMSBmb3IgbGVmdCwgNCBmb3IgbWlkZGxlCiAgICAgIC8vIElFNiBnaXZlcyAwIGZvciBsZWZ0IGFuZCBub3QgMSBhcyBJIGV4cGVjdGVkCgogICAgICBpZiAoZS5idXR0b24gPT0gNCkKICAgICAgICBtaWRkbGVjbGljayA9IHRydWU7CgogICAgICAvLyBhbGwgYnJvd3NlcnMgYWdyZWUgb24gMiBmb3IgcmlnaHQgYnV0dG9uCiAgICAgIHJpZ2h0Y2xpY2sgPSAoZS5idXR0b24gPT0gMik7CiAgICB9CiAgICBlbHNlCiAgICAgIGxlZnRjbGljayA9IHRydWU7CgogICAgaWYgKHczY19zbGlkeS5zZWxlY3RlZF90ZXh0X2xlbiA+IDApCiAgICB7CiAgICAgIHczY19zbGlkeS5zdG9wX3Byb3BhZ2F0aW9uKGUpOwogICAgICBlLmNhbmNlbCA9IHRydWU7CiAgICAgIGUucmV0dXJuVmFsdWUgPSBmYWxzZTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIC8vIGRpc21pc3MgdGFibGUgb2YgY29udGVudHMKICAgIHczY19zbGlkeS5oaWRlX3RhYmxlX29mX2NvbnRlbnRzKGZhbHNlKTsKCiAgICAvLyBjaGVjayBpZiB0YXJnZXQgaXMgc29tZXRoaW5nIHRoYXQgcHJvYmFibHkgd2FudCdzIGNsaWNrcwogICAgLy8gZS5nLiBhLCBlbWJlZCwgb2JqZWN0LCBpbnB1dCwgdGV4dGFyZWEsIHNlbGVjdCwgb3B0aW9uCiAgICB2YXIgdGFnID0gdGFyZ2V0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7CgogICAgaWYgKHczY19zbGlkeS5tb3VzZV9jbGlja19lbmFibGVkICYmIGxlZnRjbGljayAmJgogICAgICAgICF3M2Nfc2xpZHkuc3BlY2lhbF9lbGVtZW50KHRhcmdldCkgJiYKICAgICAgICAhdGFyZ2V0Lm9uY2xpY2spCiAgICB7CiAgICAgIHczY19zbGlkeS5uZXh0X3NsaWRlKHRydWUpOwogICAgICB3M2Nfc2xpZHkuc3RvcF9wcm9wYWdhdGlvbihlKTsKICAgICAgZS5jYW5jZWwgPSB0cnVlOwogICAgICBlLnJldHVyblZhbHVlID0gZmFsc2U7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9LAoKICBzcGVjaWFsX2VsZW1lbnQ6IGZ1bmN0aW9uIChlbGVtZW50KSB7CiAgICBpZiAodGhpcy5oYXNfY2xhc3MoZWxlbWVudCwgIm5vbi1pbnRlcmFjdGl2ZSIpKQogICAgICByZXR1cm4gZmFsc2U7CgogICAgdmFyIHRhZyA9IGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTsKCiAgICByZXR1cm4gZWxlbWVudC5vbmtleWRvd24gfHwKICAgICAgZWxlbWVudC5vbmNsaWNrIHx8CiAgICAgIHRhZyA9PSAiYSIgfHwKICAgICAgdGFnID09ICJlbWJlZCIgfHwKICAgICAgdGFnID09ICJvYmplY3QiIHx8CiAgICAgIHRhZyA9PSAidmlkZW8iIHx8CiAgICAgIHRhZyA9PSAiYXVkaW8iIHx8CiAgICAgIHRhZyA9PSAic3ZnIiB8fAogICAgICB0YWcgPT0gImNhbnZhcyIgfHwKICAgICAgdGFnID09ICJpbnB1dCIgfHwKICAgICAgdGFnID09ICJ0ZXh0YXJlYSIgfHwKICAgICAgdGFnID09ICJzZWxlY3QiIHx8CiAgICAgIHRhZyA9PSAib3B0aW9uIjsKICB9LAoKICBzbGlkeV9jaHJvbWU6IGZ1bmN0aW9uIChlbCkgewogICAgd2hpbGUgKGVsKQogICAgewogICAgICBpZiAoZWwgPT0gdzNjX3NsaWR5LnRvYyB8fAogICAgICAgICAgZWwgPT0gdzNjX3NsaWR5LnRvb2xiYXIgfHwKICAgICAgICAgIHczY19zbGlkeS5oYXNfY2xhc3MoZWwsICJvdXRsaW5lIikpCiAgICAgICAgcmV0dXJuIHRydWU7CgogICAgICBlbCA9IGVsLnBhcmVudE5vZGU7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0sCgogIGdldF9rZXk6IGZ1bmN0aW9uIChlKQogIHsKICAgIHZhciBrZXk7CgogICAgLy8ga2x1ZGdlIGFyb3VuZCBOUy9JRSBkaWZmZXJlbmNlcyAKICAgIGlmICh0eXBlb2Ygd2luZG93LmV2ZW50ICE9ICJ1bmRlZmluZWQiKQogICAgICBrZXkgPSB3aW5kb3cuZXZlbnQua2V5Q29kZTsKICAgIGVsc2UgaWYgKGUud2hpY2gpCiAgICAgIGtleSA9IGUud2hpY2g7CgogICAgcmV0dXJuIGtleTsKICB9LAoKICBnZXRfdGFyZ2V0OiBmdW5jdGlvbiAoZSkgewogICAgdmFyIHRhcmdldDsKCiAgICBpZiAoIWUpCiAgICAgIGUgPSB3aW5kb3cuZXZlbnQ7CgogICAgaWYgKGUudGFyZ2V0KQogICAgICB0YXJnZXQgPSBlLnRhcmdldDsKICAgIGVsc2UgaWYgKGUuc3JjRWxlbWVudCkKICAgICAgdGFyZ2V0ID0gZS5zcmNFbGVtZW50OwoKICAgIGlmICh0YXJnZXQubm9kZVR5cGUgIT0gMSkKICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnBhcmVudE5vZGU7CgogICAgcmV0dXJuIHRhcmdldDsKICB9LAoKICAvLyBkb2VzIGRpc3BsYXkgcHJvcGVydHkgcHJvdmlkZSBjb3JyZWN0IGRlZmF1bHRzPwogIGlzX2Jsb2NrOiBmdW5jdGlvbiAoZWxlbSkgewogICAgdmFyIHRhZyA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTsKCiAgICByZXR1cm4gdGFnID09ICJvbCIgfHwgdGFnID09ICJ1bCIgfHwgdGFnID09ICJwIiB8fCB0YWcgPT0gImRsIiB8fAogICAgICAgICAgIHRhZyA9PSAibGkiIHx8IHRhZyA9PSAidGFibGUiIHx8IHRhZyA9PSAicHJlIiB8fAogICAgICAgICAgIHRhZyA9PSAiaDEiIHx8IHRhZyA9PSAiaDIiIHx8IHRhZyA9PSAiaDMiIHx8CiAgICAgICAgICAgdGFnID09ICJoNCIgfHwgdGFnID09ICJoNSIgfHwgdGFnID09ICJoNiIgfHwKICAgICAgICAgICB0YWcgPT0gImJsb2NrcXVvdGUiIHx8IHRhZyA9PSAiYWRkcmVzcyI7IAogIH0sCgogIGFkZF9saXN0ZW5lcjogZnVuY3Rpb24gKGVsZW1lbnQsIGV2ZW50LCBoYW5kbGVyKSB7CiAgICBpZiAod2luZG93LmFkZEV2ZW50TGlzdGVuZXIpCiAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlciwgZmFsc2UpOwogICAgZWxzZQogICAgICBlbGVtZW50LmF0dGFjaEV2ZW50KCJvbiIrZXZlbnQsIGhhbmRsZXIpOwogIH0sCgogIC8vIHVzZWQgdG8gcHJldmVudCBldmVudCBwcm9wYWdhdGlvbiBmcm9tIGZpZWxkIGNvbnRyb2xzCiAgc3RvcF9wcm9wYWdhdGlvbjogZnVuY3Rpb24gKGV2ZW50KSB7CiAgICBldmVudCA9IGV2ZW50ID8gZXZlbnQgOiB3aW5kb3cuZXZlbnQ7CiAgICBldmVudC5jYW5jZWxCdWJibGUgPSB0cnVlOyAgLy8gZm9yIElFCgogICAgaWYgKGV2ZW50LnN0b3BQcm9wYWdhdGlvbikKICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7CgogICAgcmV0dXJuIHRydWU7CiAgfSwKCiAgY2FuY2VsOiBmdW5jdGlvbiAoZXZlbnQpIHsKICAgIGlmIChldmVudCkKICAgIHsKICAgICAgIGV2ZW50LmNhbmNlbCA9IHRydWU7CiAgICAgICBldmVudC5yZXR1cm5WYWx1ZSA9IGZhbHNlOwoKICAgICAgaWYgKGV2ZW50LnByZXZlbnREZWZhdWx0KQogICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICB9CgogICAgdzNjX3NsaWR5LmtleV93YW50ZWQgPSBmYWxzZTsKICAgIHJldHVybiBmYWxzZTsKICB9LAoKLy8gZm9yIGVhY2ggbGFuZ3VhZ2UgZGVmaW5lIGFuIGFzc29jaWF0aXZlIGFycmF5Ci8vIGFuZCBhbHNvIHRoZSBoZWxwIHRleHQgd2hpY2ggaXMgbG9uZ2VyCgogIHN0cmluZ3NfZXM6IHsKICAgICJzbGlkZSI6InDDoWcuIiwKICAgICJoZWxwPyI6IkF5dWRhIiwKICAgICJjb250ZW50cz8iOiLDjW5kaWNlIiwKICAgICJ0YWJsZSBvZiBjb250ZW50cyI6InRhYmxhIGRlIGNvbnRlbmlkb3MiLAogICAgIlRhYmxlIG9mIENvbnRlbnRzIjoiVGFibGEgZGUgQ29udGVuaWRvcyIsCiAgICAicmVzdGFydCBwcmVzZW50YXRpb24iOiJSZWluaWNpYXIgcHJlc2VudGFjacOzbiIsCiAgICAicmVzdGFydD8iOiJJbmljaW8iCiAgfSwKICBoZWxwX2VzOgogICAgIlV0aWxpY2UgZWwgcmF0w7NuLCBiYXJyYSBlc3BhY2lhZG9yYSwgdGVjbGFzIEl6ZGEvRGNoYSwgIiArCiAgICAibyBSZSBww6FnIHkgQXYgcMOhZy4gVXNlIFMgeSBCIHBhcmEgY2FtYmlhciBlbCB0YW1hw7FvIGRlIGZ1ZW50ZS4iLAoKICBzdHJpbmdzX2NhOiB7CiAgICAic2xpZGUiOiJww6BnLi4iLAogICAgImhlbHA/IjoiQWp1ZGEiLAogICAgImNvbnRlbnRzPyI6IsONbmRleCIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiJ0YXVsYSBkZSBjb250aW5ndXRzIiwKICAgICJUYWJsZSBvZiBDb250ZW50cyI6IlRhdWxhIGRlIENvbnRpbmd1dHMiLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoiUmVpbmljaWFyIHByZXNlbnRhY2nDsyIsCiAgICAicmVzdGFydD8iOiJJbmljaSIKICB9LAogIGhlbHBfY2E6CiAgICAiVXRpbGl0emkgZWwgcmF0b2zDrSwgYmFycmEgZXNwYWlhZG9yYSwgdGVjbGVzIEVzcS4vRHRhLiAiICsKICAgICJvIFJlIHDDoGcgeSBBdiBww6BnLiBVc2kgUyBpIEIgcGVyIGNhbnZpYXIgZ3JhbmTDoHJpYSBkZSBmb250LiIsCgogIHN0cmluZ3NfY3M6IHsKICAgICJzbGlkZSI6InNuw61tZWsiLAogICAgImhlbHA/IjoibsOhcG92xJtkYSIsCiAgICAiY29udGVudHM/Ijoib2JzYWgiLAogICAgInRhYmxlIG9mIGNvbnRlbnRzIjoib2JzYWggcHJlemVudGFjZSIsCiAgICAiVGFibGUgb2YgQ29udGVudHMiOiJPYnNhaCBwcmV6ZW50YWNlIiwKICAgICJyZXN0YXJ0IHByZXNlbnRhdGlvbiI6Inpub3Z1IHNwdXN0aXQgcHJlemVudGFjaSIsCiAgICAicmVzdGFydD8iOiJyZXN0YXJ0IgogIH0sCiAgaGVscF9jczoKICAgICJQcmV6ZW50YWNpIG3Fr8W+ZXRlIHByb2Now6F6ZXQgcG9tb2PDrSBrbGlrbnV0w60gbXnFoWksIG1lemVybsOta3UsICIgKwogICAgIsWhaXBlayB2bGV2byBhIHZwcmF2byBuZWJvIGtsw6F2ZXMgUGFnZVVwIGEgUGFnZURvd24uIFDDrXNtbyBzZSAiICsKICAgICJkw6EgenbEm3TFoWl0IGEgem1lbsWhaXQgcG9tb2PDrSBrbMOhdmVzIEIgYSBTLiIsCgogIHN0cmluZ3Nfbmw6IHsKICAgICJzbGlkZSI6InBhZ2luYSIsCiAgICAiaGVscD8iOiJIZWxwPyIsCiAgICAiY29udGVudHM/IjoiSW5ob3VkPyIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiJpbmhvdWRzb3BnYXZlIiwKICAgICJUYWJsZSBvZiBDb250ZW50cyI6IkluaG91ZHNvcGdhdmUiLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoiaGVyc3RhcnQgcHJlc2VudGF0aWUiLAogICAgInJlc3RhcnQ/IjoiSGVyc3RhcnQ/IgogIH0sCiAgaGVscF9ubDoKICAgICAiTmF2aWdlZXIgZC5tLnYuIGhldCBtdWlzLCBzcGF0aWViYXIsIExpbmtzL1JlY2h0cyB0b2V0c2VuLCAiICsKICAgICAib2YgUGdVcCBlbiBQZ0RuLiBHZWJydWlrIFMgZW4gQiBvbSBkZSBrYXJha3Rlcmdyb290dGUgdGUgdmVyYW5kZXJlbi4iLAoKICBzdHJpbmdzX2RlOiB7CiAgICAic2xpZGUiOiJTZWl0ZSIsCiAgICAiaGVscD8iOiJIaWxmZSIsCiAgICAiY29udGVudHM/Ijoiw5xiZXJzaWNodCIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiJJbmhhbHRzdmVyemVpY2huaXMiLAogICAgIlRhYmxlIG9mIENvbnRlbnRzIjoiSW5oYWx0c3ZlcnplaWNobmlzIiwKICAgICJyZXN0YXJ0IHByZXNlbnRhdGlvbiI6IlByw6RzZW50YXRpb24gbmV1IHN0YXJ0ZW4iLAogICAgInJlc3RhcnQ/IjoiTmV1c3RhcnQiCiAgfSwKICBoZWxwX2RlOgogICAgIkJlbnV0emVuIFNpZSBkaWUgTWF1cywgTGVlcnNjaGxhZywgZGllIEN1cnNvcnRhc3RlbiBsaW5rcy9yZWNodHMgb2RlciAiICsKICAgICJQYWdlIHVwL1BhZ2UgRG93biB6dW0gV2VjaHNlbG4gZGVyIFNlaXRlbiB1bmQgUyB1bmQgQiBmw7xyIGRpZSBTY2hyaWZ0Z3LDtnNzZS4iLAoKICBzdHJpbmdzX3BsOiB7CiAgICAic2xpZGUiOiJzbGFqZCIsCiAgICAiaGVscD8iOiJwb21vYz8iLAogICAgImNvbnRlbnRzPyI6InNwaXMgdHJlxZtjaT8iLAogICAgInRhYmxlIG9mIGNvbnRlbnRzIjoic3BpcyB0cmXFm2NpIiwKICAgICJUYWJsZSBvZiBDb250ZW50cyI6IlNwaXMgVHJlxZtjaSIsCiAgICAicmVzdGFydCBwcmVzZW50YXRpb24iOiJSZXN0YXJ0dWogcHJlemVudGFjasSZIiwKICAgICJyZXN0YXJ0PyI6InJlc3RhcnQ/IgogIH0sCiAgaGVscF9wbDoKICAgICJabWllbmlhaiBzbGFqZHkga2xpa2FqxIVjIG15c3rEhSwgbmFjaXNrYWrEhWMgc3BhY2rEmSwgc3RyemHFgmtpIGxld28vcHJhd28iICsKICAgICJsdWIgUGdVcCAvIFBnRG4uIFXFvHlqIGtsYXdpc3p5IFMgaSBCLCBhYnkgem1pZW5pxIcgcm96bWlhciBjemN6aW9ua2kuIiwKCiAgc3RyaW5nc19mcjogewogICAgInNsaWRlIjoicGFnZSIsCiAgICAiaGVscD8iOiJBaWRlIiwKICAgICJjb250ZW50cz8iOiJJbmRleCIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiJ0YWJsZSBkZXMgbWF0acOocmVzIiwKICAgICJUYWJsZSBvZiBDb250ZW50cyI6IlRhYmxlIGRlcyBtYXRpw6hyZXMiLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoiUmVjb21tZW5jZXIgbCdleHBvc8OpIiwKICAgICJyZXN0YXJ0PyI6IkTDqWJ1dCIKICB9LAogIGhlbHBfZnI6CiAgICAiTmF2aWd1ZXogYXZlYyBsYSBzb3VyaXMsIGxhIGJhcnJlIGQnZXNwYWNlLCBsZXMgZmzDqGNoZXMgIiArCiAgICAiZ2F1Y2hlL2Ryb2l0ZSBvdSBsZXMgdG91Y2hlcyBQZyBVcCwgUGcgRG4uIFV0aWxpc2V6ICIgKwogICAgImxlcyB0b3VjaGVzIFMgZXQgQiBwb3VyIG1vZGlmaWVyIGxhIHRhaWxsZSBkZSBsYSBwb2xpY2UuIiwKCiAgc3RyaW5nc19odTogewogICAgInNsaWRlIjoib2xkYWwiLAogICAgImhlbHA/Ijoic2Vnw610c8OpZyIsCiAgICAiY29udGVudHM/IjoidGFydGFsb20iLAogICAgInRhYmxlIG9mIGNvbnRlbnRzIjoidGFydGFsb21qZWd5esOpayIsCiAgICAiVGFibGUgb2YgQ29udGVudHMiOiJUYXJ0YWxvbWplZ3l6w6lrIiwKICAgICJyZXN0YXJ0IHByZXNlbnRhdGlvbiI6ImJlbXV0YXTDsyDDumpyYWluZMOtdMOhc2EiLAogICAgInJlc3RhcnQ/Ijoiw7pqcmFpbmTDrXTDoXMiCiAgfSwKICBoZWxwX2h1OgogICAgIkF6IG9sZGFsYWsga8O2enRpIGzDqXBrZWTDqXNoZXoga2F0dGludHNvbiBheiBlZ8OpcnJlbCwgdmFneSAiICsKICAgICJoYXN6bsOhbGphIGEgc3rDs2vDtnosIGEgYmFsLCB2YWd5IGEgam9iYiBuecOtbCwgaWxsZXR2ZSBhIFBhZ2UgRG93biwgIiArCiAgICAiUGFnZSBVcCBiaWxsZW50ecWxa2V0LiBBeiBTIMOpcyBhIEIgYmlsbGVudHnFsWtrZWwgdsOhbHRvenRhdGhhdGphICIgKwogICAgImEgc3rDtnZlZyBtw6lyZXTDqXQuIiwKCiAgc3RyaW5nc19pdDogewogICAgInNsaWRlIjoicGFnLiIsCiAgICAiaGVscD8iOiJBaXV0byIsCiAgICAiY29udGVudHM/IjoiSW5kaWNlIiwKICAgICJ0YWJsZSBvZiBjb250ZW50cyI6ImluZGljZSIsCiAgICAiVGFibGUgb2YgQ29udGVudHMiOiJJbmRpY2UiLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoiUmljb21pbmNpYXJlIGxhIHByZXNlbnRhemlvbmUiLAogICAgInJlc3RhcnQ/IjoiSW5pemlvIgogIH0sCiAgaGVscF9pdDoKICAgICJOYXZpZ2FyZSBjb24gbW91c2UsIGJhcnJhIHNwYXppbywgZnJlY2NlIHNpbmlzdHJhL2Rlc3RyYSBvICIgKwogICAgIlBnVXAgZSBQZ0RuLiBVc2FyZSBTIGUgQiBwZXIgY2FtYmlhcmUgbGEgZGltZW5zaW9uZSBkZWkgY2FyYXR0ZXJpLiIsCgogIHN0cmluZ3NfZWw6IHsKICAgICJzbGlkZSI6Is+DzrXOu86vzrTOsSIsCiAgICAiaGVscD8iOiLOss6/zq7OuM61zrnOsTsiLAogICAgImNvbnRlbnRzPyI6Is+AzrXPgc65zrXPh8+MzrzOtc69zrE7IiwKICAgICJ0YWJsZSBvZiBjb250ZW50cyI6Is+Azq/Ovc6xzrrOsc+CIM+AzrXPgc65zrXPh86/zrzOrc69z4nOvSIsCiAgICAiVGFibGUgb2YgQ29udGVudHMiOiLOoM6vzr3Osc66zrHPgiDOoM61z4HOuc61z4fOv868zq3Ovc+Jzr0iLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoizrXPgM6xzr3Otc66zrrOr869zrfPg863IM+AzrHPgc6/z4XPg86vzrHPg863z4IiLAogICAgInJlc3RhcnQ/IjoizrXPgM6xzr3Otc66zrrOr869zrfPg863OyIKICB9LAogIGhlbHBfZWw6CiAgICAizqDOu86/zrfOs863zrjOtc6vz4TOtSDOvM61IM+Ezr8gzrrOu86vzrogz4TOv8+FIM+Azr/Ovc+EzrnOus65zr/PjSwgz4TOvyBzcGFjZSwgz4TOsSDOss6tzrvOtyDOsc+BzrnPg8+EzrXPgc6sL860zrXOvs65zqwsICIgKwogICAgIs6uIFBhZ2UgVXAgzrrOsc65IFBhZ2UgRG93bi4gzqfPgc63z4POuc68zr/PgM6/zrnOrs+Dz4TOtSDPhM6xIM+AzrvOrs66z4TPgc6xIFMgzrrOsc65IEIgzrPOuc6xIM69zrEgzrHOu867zqzOvs61z4TOtSAiICsKICAgICLPhM6/IM68zq3Os861zrjOv8+CIM+EzrfPgiDOs8+BzrHOvM68zrHPhM6/z4POtc65z4HOrM+CLiIsCgogIHN0cmluZ3NfamE6IHsKICAgICJzbGlkZSI6IuOCueODqeOCpOODiSIsCiAgICAiaGVscD8iOiLjg5jjg6vjg5ciLAogICAgImNvbnRlbnRzPyI6IuebruasoSIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiLnm67mrKHjgpLooajnpLoiLAogICAgIlRhYmxlIG9mIENvbnRlbnRzIjoi55uu5qyhIiwKICAgICJyZXN0YXJ0IHByZXNlbnRhdGlvbiI6IuacgOWIneOBi+OCieWGjeeUnyIsCiAgICAicmVzdGFydD8iOiLmnIDliJ3jgYvjgokiCiAgfSwKICBoZWxwX2phOgogICAgICLjg57jgqbjgrnlt6bjgq/jg6rjg4Pjgq8g44O7IOOCueODmuODvOOCuSDjg7sg5bem5Y+z44Kt44O8ICIgKwogICAgICLjgb7jgZ/jga8gUGFnZSBVcCDjg7sgUGFnZSBEb3du44Gn5pON5L2c77yMIFMg44O7IELjgafjg5Xjgqnjg7Pjg4jjgrXjgqTjgrrlpInmm7QiLAoKICBzdHJpbmdzX3poOiB7CiAgICAic2xpZGUiOiLlubvnga/niYciLAogICAgImhlbHA/Ijoi5biu5YqpPyIsCiAgICAiY29udGVudHM/Ijoi5YaF5a65PyIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiLnm67lvZUiLAogICAgIlRhYmxlIG9mIENvbnRlbnRzIjoi55uu5b2VIiwKICAgICJyZXN0YXJ0IHByZXNlbnRhdGlvbiI6IumHjeaWsOWQr+WKqOWxleekuiIsCiAgICAicmVzdGFydD8iOiLph43mlrDlkK/liqg/IgogIH0sCiAgaGVscF96aDoKICAgICLnlKjpvKDmoIfngrnlh7ssIOepuuagvOadoSwg5bem5Y+z566t5aS0LCBQZyBVcCDlkowgUGcgRG4g5a+86IiqLiAiICsKICAgICLnlKggUywgQiDmlLnlj5jlrZfkvZPlpKflsI8uIiwKCiAgc3RyaW5nc19ydTogewogICAgInNsaWRlIjoi0YHQu9Cw0LnQtCIsCiAgICAiaGVscD8iOiLQv9C+0LzQvtGJ0Yw/IiwKICAgICJjb250ZW50cz8iOiLRgdC+0LTQtdGA0LbQsNC90LjQtT8iLAogICAgInRhYmxlIG9mIGNvbnRlbnRzIjoi0L7Qs9C70LDQstC70LXQvdC40LUiLAogICAgIlRhYmxlIG9mIENvbnRlbnRzIjoi0J7Qs9C70LDQstC70LXQvdC40LUiLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoi0L/QtdGA0LXQt9Cw0L/Rg9GB0YLQuNGC0Ywg0L/RgNC10LfQtdC90YLQsNGG0LjRjiIsCiAgICAicmVzdGFydD8iOiLQv9C10YDQtdC30LDQv9GD0YHQuj8iCiAgfSwKICBoZWxwX3J1OgogICAgItCf0LXRgNC10LzQtdGJ0LDQudGC0LXRgdGMINC60LvQuNC60LDRjyDQvNGL0YjQutC+0LksINC40YHQv9C+0LvRjNC30YPRjyDQutC70LDQstC40YjRgyDQv9GA0L7QsdC10LssINGB0YLRgNC10LvQutC4IiArCiAgICAi0LLQu9C10LLQvi/QstC/0YDQsNCy0L4g0LjQu9C4IFBnIFVwINC4IFBnIERuLiDQmtC70LDQstC40YjQuCBTINC4IEIg0LzQtdC90Y/RjtGCINGA0LDQt9C80LXRgCDRiNGA0LjRhNGC0LAuIiwKCiAgc3RyaW5nc19zdjogewogICAgInNsaWRlIjoic2lkYSIsCiAgICAiaGVscD8iOiJoasOkbHAiLAogICAgImNvbnRlbnRzPyI6ImlubmVow6VsbCIsCiAgICAidGFibGUgb2YgY29udGVudHMiOiJpbm5laMOlbGxzZsO2cnRlY2tuaW5nIiwKICAgICJUYWJsZSBvZiBDb250ZW50cyI6IklubmVow6VsbHNmw7ZydGVja25pbmciLAogICAgInJlc3RhcnQgcHJlc2VudGF0aW9uIjoidmlzYSBwcmVzZW50YXRpb25lbiBmcsOlbiBiw7ZyamFuIiwKICAgICJyZXN0YXJ0PyI6ImLDtnJqYSBvbSIKICB9LAogIGhlbHBfc3Y6CiAgICAiQmzDpGRkcmEgbWVkIGV0dCBrbGljayBtZWQgdsOkbnN0cmEgbXVza25hcHBlbiwgbWVsbGFuc2xhZ3N0YW5nZW50ZW4sICIgKwogICAgInbDpG5zdGVyLSBvY2ggaMO2Z2VycGlsdGFuZ2VudGVybmEgZWxsZXIgdGFuZ2VudGVybmEgUGcgVXAsIFBnIERuLiAiICsKICAgICJBbnbDpG5kIHRhbmdlbnRlcm5hIFMgb2NoIEIgZsO2ciBhdHQgw6RuZHJhIHRleHRlbnMgc3Rvcmxlay4iLAoKICBzdHJpbmdzOiB7IH0sCgogIGxvY2FsaXplOiBmdW5jdGlvbiAoc3JjKSB7CiAgICBpZiAoc3JjID09ICIiKQogICAgICByZXR1cm4gc3JjOwoKICAgICAvLyB0cnkgZnVsbCBsYW5ndWFnZSBjb2RlLCBlLmcuIGVuLVVTCiAgICAgdmFyIHMsIGxvb2t1cCA9IHczY19zbGlkeS5zdHJpbmdzW3czY19zbGlkeS5sYW5nXTsKCiAgICAgaWYgKGxvb2t1cCkKICAgICB7CiAgICAgICBzID0gbG9va3VwW3NyY107CgogICAgICAgaWYgKHMpCiAgICAgICAgcmV0dXJuIHM7CiAgICAgfQoKICAgICAvLyBzdHJpcCBjb3VudHJ5IGNvZGUgc3VmZml4LCBlLmcuCiAgICAgLy8gdHJ5IGVuIGlmIHVuZGVmaW5lZCBmb3IgZW4tVVMKICAgICB2YXIgbGcgPSB3M2Nfc2xpZHkubGFuZy5zcGxpdCgiLSIpOwoKICAgICBpZiAobGcubGVuZ3RoID4gMSkKICAgICB7CiAgICAgICBsb29rdXAgPSB3M2Nfc2xpZHkuc3RyaW5nc1tsZ1swXV07CgogICAgICAgaWYgKGxvb2t1cCkKICAgICAgIHsKICAgICAgICAgcyA9IGxvb2t1cFtzcmNdOwoKICAgICAgICAgaWYgKHMpCiAgICAgICAgICByZXR1cm4gczsKICAgICAgIH0KICAgICB9CgogICAgIC8vIG90aGVyd2lzZSBzdHJpbmcgYXMgaXMKICAgICByZXR1cm4gc3JjOwogIH0sCgogIGluaXRfbG9jYWxpemF0aW9uOiBmdW5jdGlvbiAoKSB7CiAgICB2YXIgaTE4biA9IHczY19zbGlkeTsKICAgIHZhciBoZWxwX3RleHQgPSB3M2Nfc2xpZHkuaGVscF90ZXh0OwoKICAgIC8vIGVhY2ggc3VjaCBsYW5ndWFnZSBhcnJheSBpcyBkZWNsYXJlZCBpbiB0aGUgbG9jYWxpemUgYXJyYXkKICAgIC8vIHRoaXMgaXMgdXNlZCBhcyBpbiAgdzNjX3NsaWR5LmxvY2FsaXplKCJmb28iKTsKICAgIHRoaXMuc3RyaW5ncyA9IHsKICAgICAgImVzIjp0aGlzLnN0cmluZ3NfZXMsCiAgICAgICJjYSI6dGhpcy5zdHJpbmdzX2NhLAogICAgICAiY3MiOnRoaXMuc3RyaW5nc19jcywKICAgICAgIm5sIjp0aGlzLnN0cmluZ3NfbmwsCiAgICAgICJkZSI6dGhpcy5zdHJpbmdzX2RlLAogICAgICAicGwiOnRoaXMuc3RyaW5nc19wbCwKICAgICAgImZyIjp0aGlzLnN0cmluZ3NfZnIsCiAgICAgICJodSI6dGhpcy5zdHJpbmdzX2h1LAogICAgICAiaXQiOnRoaXMuc3RyaW5nc19pdCwKICAgICAgImVsIjp0aGlzLnN0cmluZ3NfZWwsCiAgICAgICJqcCI6dGhpcy5zdHJpbmdzX2phLAogICAgICAiemgiOnRoaXMuc3RyaW5nc196aCwKICAgICAgInJ1Ijp0aGlzLnN0cmluZ3NfcnUsCiAgICAgICJzdiI6dGhpcy5zdHJpbmdzX3N2CiAgICB9LAoKICAgIGkxOG4uc3RyaW5nc19lc1toZWxwX3RleHRdID0gaTE4bi5oZWxwX2VzOwogICAgaTE4bi5zdHJpbmdzX2NhW2hlbHBfdGV4dF0gPSBpMThuLmhlbHBfY2E7CiAgICBpMThuLnN0cmluZ3NfY3NbaGVscF90ZXh0XSA9IGkxOG4uaGVscF9jczsKICAgIGkxOG4uc3RyaW5nc19ubFtoZWxwX3RleHRdID0gaTE4bi5oZWxwX25sOwogICAgaTE4bi5zdHJpbmdzX2RlW2hlbHBfdGV4dF0gPSBpMThuLmhlbHBfZGU7CiAgICBpMThuLnN0cmluZ3NfcGxbaGVscF90ZXh0XSA9IGkxOG4uaGVscF9wbDsKICAgIGkxOG4uc3RyaW5nc19mcltoZWxwX3RleHRdID0gaTE4bi5oZWxwX2ZyOwogICAgaTE4bi5zdHJpbmdzX2h1W2hlbHBfdGV4dF0gPSBpMThuLmhlbHBfaHU7CiAgICBpMThuLnN0cmluZ3NfaXRbaGVscF90ZXh0XSA9IGkxOG4uaGVscF9pdDsKICAgIGkxOG4uc3RyaW5nc19lbFtoZWxwX3RleHRdID0gaTE4bi5oZWxwX2VsOwogICAgaTE4bi5zdHJpbmdzX2phW2hlbHBfdGV4dF0gPSBpMThuLmhlbHBfamE7CiAgICBpMThuLnN0cmluZ3NfemhbaGVscF90ZXh0XSA9IGkxOG4uaGVscF96aDsKICAgIGkxOG4uc3RyaW5nc19ydVtoZWxwX3RleHRdID0gaTE4bi5oZWxwX3J1OwogICAgaTE4bi5zdHJpbmdzX3N2W2hlbHBfdGV4dF0gPSBpMThuLmhlbHBfc3Y7CgogICAgdzNjX3NsaWR5LmxhbmcgPSBkb2N1bWVudC5ib2R5LnBhcmVudE5vZGUuZ2V0QXR0cmlidXRlKCJsYW5nIik7CgogICAgaWYgKCF3M2Nfc2xpZHkubGFuZykKICAgICAgdzNjX3NsaWR5LmxhbmcgPSBkb2N1bWVudC5ib2R5LnBhcmVudE5vZGUuZ2V0QXR0cmlidXRlKCJ4bWw6bGFuZyIpOwoKICAgIGlmICghdzNjX3NsaWR5LmxhbmcpCiAgICAgIHczY19zbGlkeS5sYW5nID0gImVuIjsKICB9Cn07CgovLyBoYWNrIGZvciBiYWNrIGJ1dHRvbiBiZWhhdmlvcgppZiAodzNjX3NsaWR5LmllNiB8fCB3M2Nfc2xpZHkuaWU3KQp7CiAgZG9jdW1lbnQud3JpdGUoIjxpZnJhbWUgaWQ9J2hpc3RvcnlGcmFtZScgIiArCiAgInNyYz0namF2YXNjcmlwdDpcIjxodG1sIisiPjwvIisiaHRtbD5cIicgIiArCiAgImhlaWdodD0nMScgd2lkdGg9JzEnICIgKwogICJzdHlsZT0ncG9zaXRpb246YWJzb2x1dGU7bGVmdDotODAwcHgnPjwvaWZyYW1lPiIpOwp9CgovLyBhdHRhY2ggZXZlbnQgbGlzdGVuZXJzIGZvciBpbml0aWFsaXphdGlvbgp3M2Nfc2xpZHkuc2V0X3VwKCk7CgovLyBoaWRlIHRoZSBzbGlkZXMgYXMgc29vbiBhcyBib2R5IGVsZW1lbnQgaXMgYXZhaWxhYmxlCi8vIHRvIHJlZHVjZSBhbm5veWluZyBzY3JlZW4gbWVzcyBiZWZvcmUgdGhlIG9ubG9hZCBldmVudApzZXRUaW1lb3V0KHczY19zbGlkeS5oaWRlX3NsaWRlcywgNTApOwoK"></script>
+</head>
+<body>
+<div class="slide titlepage">
+  <h1 class="title">R#1: Introduction to R and RStudio</h1>
+  <p class="author">
+Laurent Modolo <a href="mailto:laurent.modolo@ens-lyon.fr">laurent.modolo@ens-lyon.fr</a>
+  </p>
+  <p class="date">10 Oct 2019</p>
+</div>
+<div id="r1-introduction-to-r-and-rstudio" class="slide section level2">
+<h1>R#1: Introduction to R and RStudio</h1>
+<p>The goal of this practical is to familiarize yourself with R and the RStudio environment.</p>
+<p>The objectives of this session will be to:</p>
+<ul>
+<li>Understand the purpose of each pane in RStudio</li>
+<li>Do basic computation with R</li>
+<li>Define variables and assign data to variables</li>
+<li>Manage a workspace in R</li>
+<li>Call functions</li>
+<li>Manage packages</li>
+</ul>
+<p><strong><a href="http://perso.ens-lyon.fr/laurent.modolo/R/session_1_a" class="uri">http://perso.ens-lyon.fr/laurent.modolo/R/session_1_a</a></strong></p>
+<p>Press <strong>[alt] + [shift] + k</strong></p>
+</div>
+<div id="functions-are-also-variables" class="slide section level2">
+<h1>Functions are also variables</h1>
+<p>We can also define our own function with</p>
+<div class="sourceCode" id="cb1"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1"></a><span class="op">&lt;</span>FUNCTION_NAME<span class="op">&gt;</span><span class="st"> </span><span class="er">&lt;</span><span class="op">-</span><span class="st"> </span><span class="cf">function</span>(a, b){</span>
+<span id="cb1-2"><a href="#cb1-2"></a>  <span class="op">&lt;</span>RESULT_<span class="dv">1</span><span class="op">&gt;</span><span class="st"> </span><span class="er">&lt;</span><span class="op">-</span><span class="st"> </span><span class="er">&lt;</span>OPERATION_<span class="dv">1</span><span class="op">&gt;</span>(a, b)</span>
+<span id="cb1-3"><a href="#cb1-3"></a>  <span class="op">&lt;</span>RESULT_<span class="dv">2</span><span class="op">&gt;</span><span class="st"> </span><span class="er">&lt;</span><span class="op">-</span><span class="st"> </span><span class="er">&lt;</span>OPERATION_<span class="dv">2</span><span class="op">&gt;</span>(<span class="op">&lt;</span>RESULT_<span class="dv">1</span><span class="op">&gt;</span>, b)</span>
+<span id="cb1-4"><a href="#cb1-4"></a>  <span class="kw">return</span>(<span class="op">&lt;</span>RESULT_<span class="dv">2</span><span class="op">&gt;</span>)</span>
+<span id="cb1-5"><a href="#cb1-5"></a>}</span></code></pre></div>
+
+<p>write a function to test the base of the logarithm function</p>
+
+<div class="sourceCode" id="cb2"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb2-1"><a href="#cb2-1"></a>base_test &lt;-<span class="st"> </span><span class="cf">function</span>(x, base){</span>
+<span id="cb2-2"><a href="#cb2-2"></a>  log_result &lt;-<span class="st"> </span><span class="kw">logarithm</span>(x, <span class="dt">base=</span>base)</span>
+<span id="cb2-3"><a href="#cb2-3"></a>  exp_result &lt;-<span class="st"> </span>base<span class="op">^</span>log_result</span>
+<span id="cb2-4"><a href="#cb2-4"></a>  test_result &lt;-<span class="st"> </span>x <span class="op">==</span><span class="st"> </span>exp_result</span>
+<span id="cb2-5"><a href="#cb2-5"></a>  <span class="kw">return</span>(test_result)</span>
+<span id="cb2-6"><a href="#cb2-6"></a>}</span></code></pre></div>
+<p><strong><a href="http://perso.ens-lyon.fr/laurent.modolo/R/1_b" class="uri">http://perso.ens-lyon.fr/laurent.modolo/R/1_b</a></strong></p>
+</div>
+<div id="functions-are-also-variables-1" class="slide section level2">
+<h1>Functions are also variables</h1>
+<div class="sourceCode" id="cb3"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb3-1"><a href="#cb3-1"></a>base_test &lt;-<span class="st"> </span><span class="cf">function</span>(x, base){</span>
+<span id="cb3-2"><a href="#cb3-2"></a>  <span class="kw">print</span>(x)</span>
+<span id="cb3-3"><a href="#cb3-3"></a>  log_result &lt;-<span class="st"> </span><span class="kw">logarithm</span>(x, <span class="dt">base=</span>base)</span>
+<span id="cb3-4"><a href="#cb3-4"></a>  <span class="kw">print</span>(log_result)</span>
+<span id="cb3-5"><a href="#cb3-5"></a>  exp_result &lt;-<span class="st"> </span>base<span class="op">^</span>log_result</span>
+<span id="cb3-6"><a href="#cb3-6"></a>  <span class="kw">print</span>(exp_result)</span>
+<span id="cb3-7"><a href="#cb3-7"></a>  <span class="kw">print</span>(x)</span>
+<span id="cb3-8"><a href="#cb3-8"></a>  test_result &lt;-<span class="st"> </span>x <span class="op">==</span><span class="st"> </span>exp_result</span>
+<span id="cb3-9"><a href="#cb3-9"></a>  <span class="kw">return</span>(test_result)</span>
+<span id="cb3-10"><a href="#cb3-10"></a>}</span></code></pre></div>
+<p><strong><a href="http://perso.ens-lyon.fr/laurent.modolo/R/1_c" class="uri">http://perso.ens-lyon.fr/laurent.modolo/R/1_c</a></strong></p>
+</div>
+<div id="functions-are-also-variables-2" class="slide section level2">
+<h1>Functions are also variables</h1>
+<div class="sourceCode" id="cb4"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb4-1"><a href="#cb4-1"></a>base_test &lt;-<span class="st"> </span><span class="cf">function</span>(x, base){</span>
+<span id="cb4-2"><a href="#cb4-2"></a>  <span class="kw">print</span>(x)</span>
+<span id="cb4-3"><a href="#cb4-3"></a>  log_result &lt;-<span class="st"> </span><span class="kw">logarithm</span>(x, <span class="dt">base=</span>base)</span>
+<span id="cb4-4"><a href="#cb4-4"></a>  <span class="kw">print</span>(log_result)</span>
+<span id="cb4-5"><a href="#cb4-5"></a>  exp_result &lt;-<span class="st"> </span>base<span class="op">^</span>log_result</span>
+<span id="cb4-6"><a href="#cb4-6"></a>  <span class="kw">print</span>(exp_result)</span>
+<span id="cb4-7"><a href="#cb4-7"></a>  <span class="kw">print</span>(x)</span>
+<span id="cb4-8"><a href="#cb4-8"></a>  test_result &lt;-<span class="st"> </span><span class="kw">isTRUE</span>(<span class="kw">all.equal</span>(x, exp_result))</span>
+<span id="cb4-9"><a href="#cb4-9"></a>  <span class="kw">return</span>(test_result)</span>
+<span id="cb4-10"><a href="#cb4-10"></a>}</span></code></pre></div>
+<p><strong><a href="http://perso.ens-lyon.fr/laurent.modolo/R/1_d" class="uri">http://perso.ens-lyon.fr/laurent.modolo/R/1_d</a></strong></p>
+</div>
+<div id="functions-are-also-variables-3" class="slide section level2">
+<h1>Functions are also variables</h1>
+<div class="sourceCode" id="cb5"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb5-1"><a href="#cb5-1"></a>base_test &lt;-<span class="st"> </span><span class="cf">function</span>(x, base){</span>
+<span id="cb5-2"><a href="#cb5-2"></a>  <span class="kw">return</span>(<span class="kw">isTRUE</span>(<span class="kw">all.equal</span>(x, base<span class="op">^</span><span class="kw">logarithm</span>(x, <span class="dt">base=</span>base))))</span>
+<span id="cb5-3"><a href="#cb5-3"></a>}</span></code></pre></div>
+<p><strong><a href="http://perso.ens-lyon.fr/laurent.modolo/R/1_e" class="uri">http://perso.ens-lyon.fr/laurent.modolo/R/1_e</a></strong></p>
+</div>
+<div id="the-environment" class="slide section level2">
+<h1>The environment</h1>
+<p></p>
+</div>
+<div id="a-code-editor" class="slide section level2">
+<h1>A code editor</h1>
+<p></p>
+</div>
+<div id="a-code-editor-1" class="slide section level2">
+<h1>A code editor</h1>
+<p>RStudio offers you great flexibility in running code from within the editor window. There are buttons, menu choices, and keyboard shortcuts. To run the current line, you can</p>
+<ul>
+<li>Click on the Run button above the editor panel, or</li>
+<li>select “Run Lines” from the “Code” menu, or</li>
+<li>hit Ctrl+Return in Windows or Linux or Cmd+Return on OS X. To run a block of code, select it and then Run.</li>
+</ul>
+<p>If you have modified a line of code within a block of code you have just run, there is no need to reselect the section and Run, you can use the next button along, Rerun the previous region. This will run the previous code block including the modifications you have made.</p>
+</div>
+<div id="a-code-editor-2" class="slide section level2">
+<h1>A code editor</h1>
+<p>Copy your <code>logarithm</code> and <code>base_test</code> into a <code>tp_1.R</code> file</p>
+
+<p>We can now clean your environment</p>
+<div class="sourceCode" id="cb6"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">rm</span>(x)</span></code></pre></div>
+
+<div class="sourceCode" id="cb7"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb7-1"><a href="#cb7-1"></a>?rm</span></code></pre></div>
+
+<div class="sourceCode" id="cb8"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">ls</span>()</span></code></pre></div>
+
+<div class="sourceCode" id="cb9"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">rm</span>(<span class="dt">list =</span> <span class="kw">ls</span>())</span></code></pre></div>
+</div>
+<div id="installing-packages" class="slide section level2">
+<h1>Installing packages</h1>
+<div class="sourceCode" id="cb10"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">install.packages</span>(<span class="st">&quot;tidyverse&quot;</span>)</span></code></pre></div>
+<div class="sourceCode" id="cb11"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">install.packages</span>(<span class="st">&quot;ggplot2&quot;</span>)</span></code></pre></div>
+</div>
+<div id="installing-packages-1" class="slide section level2">
+<h1>Installing packages</h1>
+<p></p>
+</div>
+<div id="loading-packages" class="slide section level2">
+<h1>Loading packages</h1>
+<div class="sourceCode" id="cb12"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">sessionInfo</span>()</span></code></pre></div>
+
+<div class="sourceCode" id="cb13"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb13-1"><a href="#cb13-1"></a><span class="kw">library</span>(tidyverse)</span></code></pre></div>
+
+<div class="sourceCode" id="cb14"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb14-1"><a href="#cb14-1"></a><span class="kw">sessionInfo</span>()</span></code></pre></div>
+
+<div class="sourceCode" id="cb15"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb15-1"><a href="#cb15-1"></a><span class="kw">unloadNamespace</span>(<span class="st">&quot;tidyverse&quot;</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb16"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb16-1"><a href="#cb16-1"></a><span class="kw">sessionInfo</span>()</span></code></pre></div>
+</div>
+<div id="complex-variable-type" class="slide section level2">
+<h1>Complex variable type</h1>
+</div>
+<div id="vector-aka-list" class="slide section level2">
+<h1>Vector (aka list)</h1>
+<div class="sourceCode" id="cb17"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb17-1"><a href="#cb17-1"></a><span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb18"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb18-1"><a href="#cb18-1"></a><span class="dv">1</span><span class="op">:</span><span class="dv">5</span></span></code></pre></div>
+
+<div class="sourceCode" id="cb19"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb19-1"><a href="#cb19-1"></a><span class="dv">2</span><span class="op">^</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">5</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb20"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb20-1"><a href="#cb20-1"></a>x &lt;-<span class="st"> </span><span class="dv">1</span><span class="op">:</span><span class="dv">5</span></span>
+<span id="cb20-2"><a href="#cb20-2"></a><span class="dv">2</span><span class="op">^</span>x</span></code></pre></div>
+
+<div class="sourceCode" id="cb21"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb21-1"><a href="#cb21-1"></a><span class="kw">log</span>(x)</span>
+<span id="cb21-2"><a href="#cb21-2"></a><span class="kw">logarithm</span>(x)</span>
+<span id="cb21-3"><a href="#cb21-3"></a><span class="kw">base_test</span>(x, <span class="dt">base =</span> <span class="dv">10</span>)</span></code></pre></div>
+</div>
+<div id="vector-aka-list-1" class="slide section level2">
+<h1>Vector (aka list)</h1>
+<div class="sourceCode" id="cb22"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb22-1"><a href="#cb22-1"></a><span class="kw">typeof</span>(x)</span></code></pre></div>
+
+<div class="sourceCode" id="cb23"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb23-1"><a href="#cb23-1"></a><span class="kw">typeof</span>(x <span class="op">+</span><span class="st"> </span><span class="fl">0.5</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb24"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb24-1"><a href="#cb24-1"></a><span class="kw">is.vector</span>(x)</span></code></pre></div>
+
+<div class="sourceCode" id="cb25"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb25-1"><a href="#cb25-1"></a><span class="kw">length</span>(x)</span></code></pre></div>
+
+<div class="sourceCode" id="cb26"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb26-1"><a href="#cb26-1"></a>x[<span class="dv">5</span>]</span></code></pre></div>
+
+<div class="sourceCode" id="cb27"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb27-1"><a href="#cb27-1"></a>y &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="dt">a =</span> <span class="dv">1</span>, <span class="dt">b =</span> <span class="dv">2</span>, <span class="dt">c =</span> <span class="dv">3</span>, <span class="dt">d =</span> <span class="dv">4</span>, <span class="dt">e =</span> <span class="dv">5</span>)</span>
+<span id="cb27-2"><a href="#cb27-2"></a><span class="kw">typeof</span>(y)</span>
+<span id="cb27-3"><a href="#cb27-3"></a><span class="kw">is.vector</span>(y)</span>
+<span id="cb27-4"><a href="#cb27-4"></a><span class="kw">names</span>(y)</span>
+<span id="cb27-5"><a href="#cb27-5"></a>y[<span class="dv">1</span>]</span>
+<span id="cb27-6"><a href="#cb27-6"></a>y[<span class="st">&quot;a&quot;</span>]</span>
+<span id="cb27-7"><a href="#cb27-7"></a><span class="kw">names</span>(y) &lt;-<span class="st"> </span><span class="kw">c</span>(<span class="st">&quot;b&quot;</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb28"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb28-1"><a href="#cb28-1"></a>x <span class="op">==</span><span class="st"> </span>y</span>
+<span id="cb28-2"><a href="#cb28-2"></a><span class="kw">all.equal</span>(x, y)</span></code></pre></div>
+</div>
+<div id="vector-challenge" class="slide section level2">
+<h1>Vector challenge</h1>
+<ul>
+<li>use the <code>seq()</code> function to create a vector of even numbers</li>
+<li>You can concatenate vector with <code>c(&lt;VECTOR_1&gt;, &lt;VECTOR_2&gt;)</code>, concatenate a vector of integers with a vector of the first 5 letters of the alphabet.</li>
+<li>Check the default vectors <code>letters</code> and <code>LETTERS</code>, rewrite your previous command using them.</li>
+<li>Create a vector giving you the correspondence between small case letters and upper case letters.</li>
+</ul>
+</div>
+<div id="vector-challenge-1" class="slide section level2">
+<h1>Vector challenge</h1>
+<ul>
+<li>use the <code>seq()</code> function to create a vector of even numbers</li>
+</ul>
+<div class="sourceCode" id="cb29"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb29-1"><a href="#cb29-1"></a><span class="kw">seq</span>(<span class="dt">from=</span><span class="dv">2</span>, <span class="dt">to=</span><span class="dv">10</span>, <span class="dt">by=</span><span class="dv">2</span>)</span></code></pre></div>
+<ul>
+<li>You can concatenate vector with <code>c(&lt;VECTOR_1&gt;, &lt;VECTOR_2&gt;)</code>, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.</li>
+<li>Check the default vectors <code>letters</code> and <code>LETTERS</code>, rewrite your previous command using them.</li>
+<li>Create a vector giving you the correspondence between small case letters and upper case letters.</li>
+</ul>
+</div>
+<div id="vector-challenge-2" class="slide section level2">
+<h1>Vector challenge</h1>
+<ul>
+<li>use the <code>seq()</code> function to create a vector of even numbers</li>
+</ul>
+<div class="sourceCode" id="cb30"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb30-1"><a href="#cb30-1"></a><span class="kw">seq</span>(<span class="dt">from=</span><span class="dv">2</span>, <span class="dt">to=</span><span class="dv">10</span>, <span class="dt">by=</span><span class="dv">2</span>)</span></code></pre></div>
+<ul>
+<li>You can concatenate vector with <code>c(&lt;VECTOR_1&gt;, &lt;VECTOR_2&gt;)</code>, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.</li>
+<li>Check the default vectors <code>letters</code> and <code>LETTERS</code>, rewrite your previous command using them.</li>
+<li>Create a vector giving you the correspondence between small case letters and upper case letters.</li>
+</ul>
+</div>
+<div id="vector-challenge-3" class="slide section level2">
+<h1>Vector challenge</h1>
+<ul>
+<li>use the <code>seq()</code> function to create a vector of even numbers</li>
+<li>You can concatenate vector with <code>c(&lt;VECTOR_1&gt;, &lt;VECTOR_2&gt;)</code>, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.</li>
+</ul>
+<div class="sourceCode" id="cb31"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb31-1"><a href="#cb31-1"></a><span class="kw">c</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">5</span>, <span class="st">&quot;a&quot;</span>, <span class="st">&quot;b&quot;</span>, <span class="st">&quot;c&quot;</span>)</span>
+<span id="cb31-2"><a href="#cb31-2"></a><span class="kw">typeof</span>(<span class="kw">c</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">5</span>, <span class="st">&quot;a&quot;</span>, <span class="st">&quot;b&quot;</span>, <span class="st">&quot;c&quot;</span>))</span></code></pre></div>
+<ul>
+<li>Check the default vectors <code>letters</code> and <code>LETTERS</code>, rewrite your previous command using them.</li>
+<li>Create a vector giving you the correspondence between small case letters and upper case letters.</li>
+</ul>
+</div>
+<div id="vector-challenge-4" class="slide section level2">
+<h1>Vector challenge</h1>
+<ul>
+<li>use the <code>seq()</code> function to create a vector of even numbers</li>
+<li>You can concatenate vector with <code>c(&lt;VECTOR_1&gt;, &lt;VECTOR_2&gt;)</code>, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.</li>
+<li>Check the default vectors <code>letters</code> and <code>LETTERS</code>, rewrite your previous command using them.</li>
+</ul>
+<div class="sourceCode" id="cb32"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb32-1"><a href="#cb32-1"></a><span class="kw">c</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">5</span>, letters[<span class="dv">1</span><span class="op">:</span><span class="dv">3</span>])</span></code></pre></div>
+<ul>
+<li>Create a vector giving you the correspondence between small case letters and upper case letters.</li>
+</ul>
+</div>
+<div id="vector-challenge-5" class="slide section level2">
+<h1>Vector challenge</h1>
+<ul>
+<li>use the <code>seq()</code> function to create a vector of even numbers</li>
+<li>You can concatenate vector with <code>c(&lt;VECTOR_1&gt;, &lt;VECTOR_2&gt;)</code>, concatenate a vector of integers with a vector of the first 5 letters of the alphabet. What is the type of this vector.</li>
+<li>Check the default vectors <code>letters</code> and <code>LETTERS</code>, rewrite your previous command using them.</li>
+<li>Create a vector giving you the correspondence between small case letters and upper case letters.</li>
+</ul>
+<div class="sourceCode" id="cb33"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb33-1"><a href="#cb33-1"></a>rosette &lt;-<span class="st"> </span>LETTERS</span>
+<span id="cb33-2"><a href="#cb33-2"></a><span class="kw">names</span>(rosette) &lt;-<span class="st"> </span>letters</span>
+<span id="cb33-3"><a href="#cb33-3"></a>rosette[<span class="st">&quot;b&quot;</span>]</span>
+<span id="cb33-4"><a href="#cb33-4"></a>rosette[<span class="dv">13</span>]</span></code></pre></div>
+</div>
+<div id="matrix" class="slide section level2">
+<h1>Matrix</h1>
+<p>In R matrix are two dimensional vectors</p>
+<div class="sourceCode" id="cb34"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb34-1"><a href="#cb34-1"></a>matrix_example &lt;-<span class="st"> </span><span class="kw">matrix</span>(<span class="dv">1</span><span class="op">:</span>(<span class="dv">6</span><span class="op">*</span><span class="dv">3</span>), <span class="dt">ncol=</span><span class="dv">6</span>, <span class="dt">nrow=</span><span class="dv">3</span>)</span>
+<span id="cb34-2"><a href="#cb34-2"></a>matrix_example</span></code></pre></div>
+
+<div class="sourceCode" id="cb35"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb35-1"><a href="#cb35-1"></a><span class="kw">class</span>(matrix_example)</span>
+<span id="cb35-2"><a href="#cb35-2"></a><span class="kw">nrow</span>(matrix_example)</span>
+<span id="cb35-3"><a href="#cb35-3"></a><span class="kw">ncol</span>(matrix_example)</span></code></pre></div>
+
+<div class="sourceCode" id="cb36"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb36-1"><a href="#cb36-1"></a>matrix_example[<span class="dv">2</span>, <span class="dv">3</span>]</span></code></pre></div>
+</div>
+<div id="dataframe" class="slide section level2">
+<h1>DataFrame</h1>
+<p>In R <code>data.frame</code> are table type with mixed type</p>
+<div class="sourceCode" id="cb37"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb37-1"><a href="#cb37-1"></a>data_frame_example &lt;-<span class="st"> </span><span class="kw">data.frame</span>(<span class="dt">numbers=</span><span class="dv">1</span><span class="op">:</span><span class="dv">26</span>, <span class="dt">letters=</span>letters, <span class="dt">LETTERS=</span>LETTERS)</span>
+<span id="cb37-2"><a href="#cb37-2"></a>data_frame_example</span></code></pre></div>
+
+<div class="sourceCode" id="cb38"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb38-1"><a href="#cb38-1"></a><span class="kw">class</span>(data_frame_example)</span>
+<span id="cb38-2"><a href="#cb38-2"></a><span class="kw">nrow</span>(data_frame_example)</span>
+<span id="cb38-3"><a href="#cb38-3"></a><span class="kw">ncol</span>(data_frame_example)</span>
+<span id="cb38-4"><a href="#cb38-4"></a><span class="kw">names</span>(data_frame_example)</span></code></pre></div>
+
+<div class="sourceCode" id="cb39"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb39-1"><a href="#cb39-1"></a>data_frame_example[<span class="dv">2</span>, <span class="dv">3</span>]</span>
+<span id="cb39-2"><a href="#cb39-2"></a>data_frame_example[<span class="st">&quot;numbers&quot;</span>]</span></code></pre></div>
+</div>
+<div id="list" class="slide section level2">
+<h1>List</h1>
+<p>In R <code>list</code> are multitypes object</p>
+<div class="sourceCode" id="cb40"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb40-1"><a href="#cb40-1"></a><span class="kw">list</span>(<span class="dt">a =</span> <span class="st">&quot;test&quot;</span>, <span class="dt">b =</span> <span class="dv">1</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb41"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb41-1"><a href="#cb41-1"></a><span class="kw">list</span>(<span class="dt">a =</span> <span class="st">&quot;test&quot;</span>, <span class="dt">b =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">5</span>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb42"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb42-1"><a href="#cb42-1"></a>z &lt;-<span class="st"> </span><span class="kw">list</span>(</span>
+<span id="cb42-2"><a href="#cb42-2"></a>  <span class="dt">a =</span> <span class="st">&quot;test&quot;</span>,</span>
+<span id="cb42-3"><a href="#cb42-3"></a>  <span class="dt">b =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">5</span>,</span>
+<span id="cb42-4"><a href="#cb42-4"></a>  <span class="dt">c =</span> <span class="kw">data.frame</span>(<span class="dt">numbers=</span><span class="dv">1</span><span class="op">:</span><span class="dv">26</span>, <span class="dt">letters=</span>letters, <span class="dt">LETTERS=</span>LETTERS)</span>
+<span id="cb42-5"><a href="#cb42-5"></a>)</span></code></pre></div>
+
+<div class="sourceCode" id="cb43"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb43-1"><a href="#cb43-1"></a><span class="kw">list</span>(</span>
+<span id="cb43-2"><a href="#cb43-2"></a>  <span class="dt">a =</span> <span class="st">&quot;test&quot;</span>,</span>
+<span id="cb43-3"><a href="#cb43-3"></a>  <span class="dt">b =</span> <span class="dv">1</span><span class="op">:</span><span class="dv">5</span>,</span>
+<span id="cb43-4"><a href="#cb43-4"></a>  <span class="dt">c =</span> z</span>
+<span id="cb43-5"><a href="#cb43-5"></a>)</span></code></pre></div>
+</div>
+
+  <!-- dynamically load mathjax for compatibility with self-contained -->
+  <script>
+    (function () {
+      var script = document.createElement("script");
+      script.type = "text/javascript";
+      script.src  = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
+      document.getElementsByTagName("head")[0].appendChild(script);
+    })();
+  </script>
+
+</body>
+</html>