2d9281a1f7e7

Finish the fucking diamond square entry already
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 25 Jun 2016 15:57:05 +0000
parents a52d61eb7e85
children cc9b027d5b2a 9099c4a3d13d
branches/tags (none)
files Makefile content/blog/2016/06/diamond-square.html media/diamond-square.monopic media/js/terrain1.js media/js/terrain2.js media/js/terrain3.js media/js/wisp/terrain3.js media/js/wisp/terrain3.wisp settings.py

Changes

--- a/Makefile	Mon Mar 07 13:44:20 2016 +0000
+++ b/Makefile	Sat Jun 25 15:57:05 2016 +0000
@@ -22,7 +22,10 @@
 	cat $< | wisp > $@
 
 media/js/terrain1.js: $(javascripts)
-	browserify media/js/wisp/terrain1.js -o $@
+	browserify media/js/wisp/terrain1.js -do $@
 
 media/js/terrain2.js: $(javascripts)
-	browserify media/js/wisp/terrain2.js -o $@
+	browserify media/js/wisp/terrain2.js -do $@
+
+media/js/terrain3.js: $(javascripts)
+	browserify media/js/wisp/terrain3.js -do $@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2016/06/diamond-square.html	Sat Jun 25 15:57:05 2016 +0000
@@ -0,0 +1,475 @@
+    {% extends "_post.html" %}
+
+    {% load mathjax %}
+
+    {% hyde
+        title: "Terrain Generation with Diamond Square"
+        snip: "Improving on Midpoint Displacement."
+        created: 2016-06-27 13:45:00
+    %}
+
+    {% block extra_js %}
+        <script data-cfasync="false" src="/media/js/three.min.js"></script>
+        <script data-cfasync="false" src="/media/js/TrackballControls.js"></script>
+        <script data-cfasync="false" src="/media/js/terrain3.js"></script>
+    {% endblock extra_js %}
+
+    {% block article %}
+
+In the last two posts we looked at implementing the Midpoint Displacement
+algorithm for procedurally generating terrain.  Today we're going to look at
+a similar algorithm called Diamond Square that fixes some problems with Midpoint
+Displacement.
+
+The full series of posts so far:
+
+* [Midpoint Displacement](/blog/2016/02/midpoint-displacement/)
+* [Recursive Midpoint Displacement](/blog/2016/03/recursive-midpoint-displacement/)
+* [Diamond Square](/blog/2016/03/diamond-square/)
+
+Midpoint Displacement is fairly simple and pretty fast, but it suffers from some
+flaws.  If you look at the end result you'll probably start to notice "seams" in
+the terrain that appear on perfectly square chunks.  This happens because when
+you're calculating the midpoints of the edges of each square you're only
+averaging two sources.
+
+[Diamond Square][] is an algorithm that works a lot like Midpoint Displacement,
+but it adds an extra step to ensure that (almost) every point uses *four*
+sources of data.  This reduces the visual artifacts a lot without much extra
+effort.
+
+Let's [draw the owl][owl].
+
+[Diamond Square]: https://en.wikipedia.org/wiki/Diamond-square_algorithm
+[owl]: https://i.imgur.com/RadSf.jpg
+
+[TOC]
+
+## Overview
+
+The high-level description of Diamond Square goes something like this:
+
+1. Initialize the corners to random values.
+2. Set the center of the heightmap to the average of the corners (plus jitter).
+3. Set the midpoints of the edges of the heightmap to the average of the four
+   points on the "diamond" around them (plus jitter).
+4. Repeat steps 2-4 on successively smaller chunks of the heightmap until you
+   bottom out at 3x3 chunks.
+
+## Initialization
+
+Initialization is pretty simple:
+
+    :::clojure
+    (defn ds-init-corners [heightmap]
+      (let [last (heightmap-last-index heightmap)]
+        (heightmap-set! heightmap 0    0    (rand))
+        (heightmap-set! heightmap 0    last (rand))
+        (heightmap-set! heightmap last 0    (rand))
+        (heightmap-set! heightmap last last (rand))))
+
+Just set the corners to random values, exactly like we did in Midpoint
+Displacement.
+
+<div id="demo-1" class="threejs"></div>
+
+## Square
+
+In the "square" step of Diamond Square, we take a square region of the heightmap
+and set the center of it to the average of the four corners (plus jitter).
+
+<pre class="lineart">
+           Column
+         0 1 2 3 4         0 1 2 3 4         0 1 2 3 4
+        ┌─┬─┬─┬─┬─┐       ┌─┬─┬─┬─┬─┐       ┌─┬─┬─┬─┬─┐
+      0 │1│ │ │ │8│     0 │1│ │ │ │8│     0 │1│ │ │ │8│
+        ├─┼─┼─┼─┼─┤       ├─╲─┼─┼─╱─┤       ├─╲─┼─┼─╱─┤
+      1 │ │ │ │ │ │     1 │ │╲│ │╱│ │     1 │ │╲│ │╱│ │
+    R   ├─┼─┼─┼─┼─┤       ├─┼─◢─◣─┼─┤       ├─┼─◢─◣─┼─┤
+    o 2 │ │ │◉│ │ │     2 │ │ │◉│ │ │     2 │ │ │3│ │ │
+    w   ├─┼─┼─┼─┼─┤       ├─┼─◥─◤─┼─┤       ├─┼─◥─◤─┼─┤
+      3 │ │ │ │ │ │     3 │ │╱│ │╲│ │     3 │ │╱│ │╲│ │
+        ├─┼─┼─┼─┼─┤       ├─╱─┼─┼─╲─┤       ├─╱─┼─┼─╲─┤
+      4 │0│ │ │ │3│     4 │0│ │ │ │3│     4 │0│ │ │ │3│
+        └─┴─┴─┴─┴─┘       └─┴─┴─┴─┴─┘       └─┴─┴─┴─┴─┘
+</pre>
+
+The Wikipedia article calls this the "diamond" step, but that seems backwards to
+me.  We're operating on a *square* region of the heightmap, so this should be
+the *square* step.
+
+Since we're no longer working with heightmap "slices" like we were in the
+previous post, we'll need a way to specify the square chunk of the heightmap
+we're working on.  I chose to use a center point (`x` and `y` coordinates) and
+a radius:
+
+    :::clojure
+    (defn ds-square [heightmap x y radius spread]
+      (let [new-height
+            (jitter
+              (average4
+                (heightmap-get heightmap (- x radius) (- y radius))
+                (heightmap-get heightmap (- x radius) (+ y radius))
+                (heightmap-get heightmap (+ x radius) (- y radius))
+                (heightmap-get heightmap (+ x radius) (+ y radius)))
+              spread)]
+        (heightmap-set! heightmap x y new-height)))
+
+<div id="demo-2" class="threejs"></div>
+
+## Diamond
+
+In the "diamond" step of Diamond Square, we take a diamond-shaped region and set
+the center of it to the average of the four corners:
+
+<pre class="lineart">
+               Column
+         0 1 2 3 4 5 6 7 8        0 1 2 3 4 5 6 7 8
+        ┌─┬─┬─┬─┬─┬─┬─┬─┬─┐      ┌─┬─┬─┬─┬─┬─┬─┬─┬─┐
+      0 │1│ │ │ │3│ │ │ │3│    0 │1│ │ │ │3│ │ │ │3│
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─╱─╲─┼─┼─┼─┤
+      1 │ │ │ │ │ │ │ │ │ │    1 │ │ │ │╱│ │╲│ │ │ │
+    R   ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─╱─┼─┼─╲─┼─┼─┤
+    o 2 │ │ │3│ │ │ │4│ │ │    2 │ │ │3│ │◉│ │4│ │ │
+    w   ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─╲─┼─┼─╱─┼─┼─┤
+      3 │ │ │ │ │ │ │ │ │ │    3 │ │ │ │╲│ │╱│ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─╲─╱─┼─┼─┼─┤
+      4 │5│ │ │ │5│ │ │ │5│    4 │5│ │ │ │5│ │ │ │5│
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      5 │ │ │ │ │ │ │ │ │ │    5 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      6 │ │ │7│ │ │ │6│ │ │    6 │ │ │7│ │ │ │6│ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      7 │ │ │ │ │ │ │ │ │ │    7 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      8 │9│ │ │ │7│ │ │ │7│    8 │9│ │ │ │7│ │ │ │7│
+        └─┴─┴─┴─┴─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┴─┴─┴─┴─┘
+
+               Column
+         0 1 2 3 4 5 6 7 8        0 1 2 3 4 5 6 7 8
+        ┌─┬─┬─┬─┬─┬─┬─┬─┬─┐      ┌─┬─┬─┬─┬─┬─┬─┬─┬─┐
+      0 │1│ │ │ │3│ │ │ │3│    0 │1│ │ │ │3│ │ │ │3│
+        ├─┼─┼─┼─╱┬╲─┼─┼─┼─┤      ├─┼─┼─┼─╱┬╲─┼─┼─┼─┤
+      1 │ │ │ │╱│││╲│ │ │ │    1 │ │ │ │╱│││╲│ │ │ │
+    R   ├─┼─┼─╱─┼▼┼─╲─┼─┼─┤      ├─┼─┼─╱─┼▼┼─╲─┼─┼─┤
+    o 2 │ │ │3├─▶◉◀─┤4│ │ │    2 │ │ │3├─▶4◀─┤4│ │ │
+    w   ├─┼─┼─╲─┼▲┼─╱─┼─┼─┤      ├─┼─┼─╲─┼▲┼─╱─┼─┼─┤
+      3 │ │ │ │╲│││╱│ │ │ │    3 │ │ │ │╲│││╱│ │ │ │
+        ├─┼─┼─┼─╲┴╱─┼─┼─┼─┤      ├─┼─┼─┼─╲┴╱─┼─┼─┼─┤
+      4 │5│ │ │ │5│ │ │ │5│    4 │5│ │ │ │5│ │ │ │5│
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      5 │ │ │ │ │ │ │ │ │ │    5 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      6 │ │ │7│ │ │ │6│ │ │    6 │ │ │7│ │ │ │6│ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      7 │ │ │ │ │ │ │ │ │ │    7 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      8 │9│ │ │ │7│ │ │ │7│    8 │9│ │ │ │7│ │ │ │7│
+        └─┴─┴─┴─┴─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┴─┴─┴─┴─┘
+</pre>
+
+First we define how do do a single diamond-shaped region.  Once again we'll use
+a center point and radius to specify the region inside the heightmap:
+
+    :::clojure
+    (defn ds-diamond [heightmap x y radius spread]
+      (let [new-height
+            (jitter
+              (safe-average
+                (heightmap-get-safe heightmap (- x radius) y)
+                (heightmap-get-safe heightmap (+ x radius) y)
+                (heightmap-get-safe heightmap x (- y radius))
+                (heightmap-get-safe heightmap x (+ y radius)))
+              spread)]
+        (heightmap-set! heightmap x y new-height)))
+
+<div id="demo-3" class="threejs"></div>
+
+## Edge Cases
+
+You might have noticed that we used `heightmap-get-safe` and `safe-average` in
+the `ds-diamond` code.  This is to handle the diamonds on the edge of the
+heightmap.  Those diamonds only have three points to average:
+
+<pre class="lineart">
+           Column
+         0 1 2 3 4        0 1 2 3 4
+        ┌─┬─┬─┬─┬─┐      ┌─┬─┬─┬─┬─┐
+      0 │1│ │ │ │8│    0 │1│ │ │ │8│
+        ├─┼─┼─┼─┼─┤      ├─┼─┼─┼─╱┬╲
+      1 │ │ │ │ │ │    1 │ │ │ │╱│││╲
+    R   ├─┼─┼─┼─┼─┤      ├─┼─┼─╱─┼▼┤ ╲
+    o 2 │ │ │3│ │ │    2 │ │ │3├─▶◉◀──?
+    w   ├─┼─┼─┼─┼─┤      ├─┼─┼─╲─┼▲┤ ╱
+      3 │ │ │ │ │ │    3 │ │ │ │╲│││╱
+        ├─┼─┼─┼─┼─┤      ├─┼─┼─┼─╲┴╱
+      4 │0│ │ │ │3│    4 │0│ │ │ │3│
+        └─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┘
+</pre>
+
+So we just ignore the missing point:
+
+    :::clojure
+    (defn safe-average [a b c d]
+      (let [total 0 count 0]
+        (when a (add! total a) (inc! count))
+        (when b (add! total b) (inc! count))
+        (when c (add! total c) (inc! count))
+        (when d (add! total d) (inc! count))
+        (/ total count)))
+
+    (defn heightmap-get-safe [heightmap x y]
+      (let [last (heightmap-last-index heightmap)]
+        (when (and (<= 0 x last)
+                   (<= 0 y last))
+          (heightmap-get heightmap x y))))
+
+Technically this means they have less information to work with than the rest of
+the points, and you might see some slight artifacts.  But in practice it's not
+too bad, and it's a lot nicer than midpoint displacement where *every* line step
+uses only *two* points.
+
+Another way to handle this is to also wrap those edge coordinates around and
+pull the point from the other side of the heightmap.  This is a bit more work
+but gives you an extra benefit: the heightmap will be tileable.
+
+## Iteration
+
+Unfortunately we can't use recursion to iterate for diamond square like we did
+for midpoint displacement.  We have to interleave the diamond and square steps,
+performing each round of squares on the *entire* map before moving on to a round
+of diamonds.
+
+If we don't, bad things will happen.  Let's look at an example to see why.
+First we perform the initial square step:
+
+<pre class="lineart">
+           Column
+         0 1 2 3 4        0 1 2 3 4
+        ┌─┬─┬─┬─┬─┐      ┌─┬─┬─┬─┬─┐
+      0 │1│ │ │ │8│    0 │1│ │ │ │8│
+        ├─┼─┼─┼─┼─┤      ├─╲─┼─┼─╱─┤
+      1 │ │ │ │ │ │    1 │ │╲│ │╱│ │
+    R   ├─┼─┼─┼─┼─┤      ├─┼─◢─◣─┼─┤
+    o 2 │ │ │ │ │ │    2 │ │ │3│ │ │
+    w   ├─┼─┼─┼─┼─┤      ├─┼─◥─◤─┼─┤
+      3 │ │ │ │ │ │    3 │ │╱│ │╲│ │
+        ├─┼─┼─┼─┼─┤      ├─╱─┼─┼─╲─┤
+      4 │0│ │ │ │3│    4 │0│ │ │ │3│
+        └─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┘
+</pre>
+
+That's fine.  Then we recurse into the first of the four diamonds:
+
+<pre class="lineart">
+           Column
+         0 1 2 3 4        0 1 2 3 4
+        ┌─┬─┬─┬─┬─┐      ┌─┬─┬─┬─┬─┐
+      0 │1│ │ │ │8│    0 │1├─▶4◀─┤8│
+        ├─┼─┼─┼─┼─┤      ├─╲─┼▲┼─╱─┤
+      1 │ │ │ │ │ │    1 │ │╲│││╱│ │
+    R   ├─┼─┼─┼─┼─┤      ├─┼─╲┴╱─┼─┤
+    o 2 │ │ │3│ │ │    2 │ │ │3│ │ │
+    w   ├─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┤
+      3 │ │ │ │ │ │    3 │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┤
+      4 │0│ │ │ │3│    4 │0│ │ │ │3│
+        └─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┘
+</pre>
+
+Everything's still good.  Then we recurse into the square:
+
+<pre class="lineart">
+            Column
+         0 1 2 3 4        0 1 2 3 4
+        ┌─┬─┬─┬─┬─┐      ╔═════╗─┬─┐
+      0 │1│ │4│ │8│    0 ║1│ │4║ │8│
+        ├─┼─┼─┼─┼─┤      ║─◢─◣─║─┼─┤
+      1 │ │ │ │ │ │    1 ║ │ │ ║ │ │
+    R   ├─┼─┼─┼─┼─┤      ║─◥─◤─║─┼─┤
+    o 2 │ │ │3│ │ │    2 ║?│ │3║ │ │
+    w   ├─┼─┼─┼─┼─┤      ╚═════╝─┼─┤
+      3 │ │ │ │ │ │    3 │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┤
+      4 │0│ │ │ │3│    4 │0│ │ │ │3│
+        └─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┘
+</pre>
+
+But wait, there's a corner missing!  We needed to complete that left-hand
+diamond step to get it, but that's still waiting on the stack for this line of
+recursion to bottom out.
+
+### A "Strided" Iteration Construct
+
+So we need to use normal iteration.  We can start by writing the code to do
+a single round of diamonds or squares on the heightmap.  First we'll make a nice
+looping construct called `do-stride`:
+
+    :::clojure
+    (defmacro do-stride
+        [varnames start-form end-form stride-form & body]
+      (let [stride (gensym "stride")
+            start (gensym "start")
+            end (gensym "end")
+            build (fn build [vars]
+                    (if (empty? vars)
+                      `(do ~@body)
+                      (let [varname (first vars)]
+                        `(loop [~varname ~start]
+                           (when (< ~varname ~end)
+                             ~(build (rest vars))
+                             (recur (+ ~varname ~stride)))))))]
+        ; Fix the numbers once outside the nested loops,
+        ; and then build the guts.
+        `(let [~start ~start-form
+               ~end ~end-form
+               ~stride ~stride-form]
+           ~(build varnames))))
+
+This scary-looking macro builds the nested looping structure we'll need to
+perform the iteration for our diamonds and squares.  It abstracts away the
+tedium of writing out nested `for` loops so we can focus on the rest of the
+algorithm.
+
+`do-stride` takes a list of variables to bind, a number to start at, a number to
+end before, and a body.  For each variable it starts at `start`, runs `body`,
+increments by `stride`, and loops until the value is at or above `end`.  For
+example:
+
+* `(do-stride [x] 0 5 1 (console.log x))` will log `0 1 2 3 4`.
+* `(do-stride [x] 0 5 2 (console.log x))` will log `0 2 4`.
+* `(do-stride [x y] 0 3 2 (console.log [x y]))` will log `[0, 0] [0, 2] [2, 0]
+  [2, 2]`.
+
+### Square Iteration
+
+Now that we've got this, we can iterate our square step over the heightmap for
+a specific radius:
+
+    :::clojure
+    (defn ds-squares [heightmap radius spread]
+      (do-stride [x y] radius (heightmap-resolution heightmap) (* 2 radius)
+        (ds-square heightmap x y radius spread)))
+
+We use `do-stride` to start at the radius and loop until we fall off the
+heightmap, stepping by *twice* the radius each time.
+
+Because our heightmaps are always square we can use the same values for both
+dimensions.  `do-stride` can take zero or more variables and will just do the
+right thing, so we don't need to worry about it.
+
+The stride is double the radius because as we step between squares we move over
+the right half of the first *and* the left half of the next:
+
+<pre class="lineart">
+               Column
+          0 1 2 3 4 5 6 7 8        0 1 2 3 4 5 6 7 8
+         ╔═════════╗─┬─┬─┬─┐      ╔═════════╗─┬─┬─┬─┐
+       0 ║1│ │ │ │3║ │ │ │3│    0 ║1│ │ │ │3║ │ │ │3│
+         ║─┼─┼─┼─┼─║─┼─┼─┼─┤      ║─┼─┼─┼─┼─║─┼─┼─┼─┤
+       1 ║ │ │ │ │ ║ │ │ │ │    1 ║ │ │ │ │ ║ │ │ │ │
+    R    ║─┼─┼─┼─┼─║─┼─┼─┼─┤     radius ┼─┼─║─┼─┼─┼─┤
+    o  2 ║ │ │◉│ │ ║ │◉│ │ │    2 ║◀━━▶◉◀━━━━━▶◉│ │ │
+    w    ║─┼─┼─┼─┼─║─┼─┼─┼─┤      ║─┼─┼─ stride ┼─┼─┤
+       3 ║ │ │ │ │ ║ │ │ │ │    3 ║ │ │ │ │ ║ │ │ │ │
+         ║─┼─┼─┼─┼─║─┼─┼─┼─┤      ║─┼─┼─┼─┼─║─┼─┼─┼─┤
+       4 ║5│ │ │ │5║ │ │ │5│    4 ║5│ │ │ │5║ │ │ │5│
+         ╚═════════╝─┼─┼─┼─┤      ╚═════════╝─┼─┼─┼─┤
+       5 │ │ │ │ │ │ │ │ │ │    5 │ │ │ │ │ │ │ │ │ │
+         ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+       6 │ │ │◉│ │ │ │◉│ │ │    6 │ │ │◉│ │ │ │◉│ │ │
+         ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+       7 │ │ │ │ │ │ │ │ │ │    7 │ │ │ │ │ │ │ │ │ │
+         ├─┼─┼─┼─┼─┼─┼─┼─┼─┤      ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+       8 │9│ │ │ │7│ │ │ │7│    8 │9│ │ │ │7│ │ │ │7│
+         └─┴─┴─┴─┴─┴─┴─┴─┴─┘      └─┴─┴─┴─┴─┴─┴─┴─┴─┘
+</pre>
+
+### Diamond Iteration
+
+The diamonds are a little more complicated.
+
+First of all, in the `y` dimension we need to start at `0` instead of `radius`
+(these will be the top and bottom edge cases we looked at).  Also, in the `x`
+direction all the even iterations need to start at `radius`, while the odd
+iterations should start at `0`.
+
+Hopefully a picture will make it a bit more clear:
+
+<pre class="lineart">
+               Column
+         0 1 2 3 4 5 6 7 8
+        ┌─┬─┬─┬─┬─┬─┬─┬─┬─┐
+      0 │1│ │◉│ │3│ │◉│ │3│ y iteration: 0, start at x = radius
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      1 │ │ │ │ │ │ │ │ │ │
+    R   ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+    o 2 │◉│ │3│ │◉│ │4│ │◉│ y iteration: 1, start at x = 0
+    w   ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      3 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      4 │5│ │◉│ │5│ │◉│ │5│ y iteration: 2, start at x = radius
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      5 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      6 │◉│ │7│ │◉│ │6│ │◉│ y iteration: 3, start at x = 0
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      7 │ │ │ │ │ │ │ │ │ │
+        ├─┼─┼─┼─┼─┼─┼─┼─┼─┤
+      8 │9│ │◉│ │7│ │◉│ │7│ y iteration: 4, start at x = radius
+        └─┴─┴─┴─┴─┴─┴─┴─┴─┘
+</pre>
+
+The code for the diamonds is the hairiest bit of the algorithm.  Make sure you
+understand it before moving on.  `shift` will be `radius` for even iterations
+and `0` for odd ones:
+
+    :::clojure
+    (defn ds-diamonds [heightmap radius spread]
+      (let [size (heightmap-resolution heightmap)]
+        (do-stride [y] 0 size radius
+          (let [shift (if (even? (/ y radius)) radius 0)]
+            (do-stride [x] shift size (* 2 radius)
+              (ds-diamond heightmap x y radius spread))))))
+
+### Top-Level Iteration
+
+Finally we can put it all together.  We initialize the corners and starting
+values, then loop over smaller and smaller radii and just call `ds-squares` and
+`ds-diamonds` to do the heavy lifting:
+
+    :::clojure
+    (defn diamond-square [heightmap]
+      (let [initial-spread 0.3
+            spread-reduction 0.5
+            center (heightmap-center-index heightmap)
+            size (aget heightmap.shape 0)]
+        (ds-init-corners heightmap)
+        (loop [radius center
+               spread initial-spread]
+          (when (>= radius 1)
+            (ds-squares heightmap radius spread)
+            (ds-diamonds heightmap radius spread)
+            (recur (/ radius 2)
+                   (* spread spread-reduction))))
+        (sanitize heightmap)))
+
+## Result
+
+The end result looks like this:
+
+<div id="demo-final" class="threejs"></div>
+
+It looks a lot like the result from midpoint displacement, but without the ugly
+seams around the square chunks.
+
+The code for these blog posts is a bit of a mess because I've been copy/pasting
+to show the partially-completed demos after each step.  I've created a little
+[single-page demo][ymir] with completed versions of the various algorithms you
+can play with, and [that code][ymir-code] should be a lot more readable than the
+hacky code for these posts.
+
+[ymir]: http://ymir.stevelosh.com/
+[ymir-code]: http://bitbucket.org/sjl/ymir/
+
+    {% endblock article %}
Binary file media/diamond-square.monopic has changed
--- a/media/js/terrain1.js	Mon Mar 07 13:44:20 2016 +0000
+++ b/media/js/terrain1.js	Sat Jun 25 15:57:05 2016 +0000
@@ -520,4 +520,5 @@
 $(run);
 
 
-},{}]},{},[1]);
+},{}]},{},[1])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm1lZGlhL2pzL3dpc3AvYW5vbnltb3VzLndpc3AiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNDQSxJQUFLLEtBQUEsR0FBQSxPQUFBLENBQUEsS0FBQSxHQUFNLEdBQVg7QUFDQSxJQUFLLE1BQUEsR0FBQSxPQUFBLENBQUEsTUFBQSxHQUFPLEdBQVosQ0FEQTtBQUVBLElBQUssU0FBQSxHQUFBLE9BQUEsQ0FBQSxTQUFBLEcsSUFBTCxDQUZBO0FBR0EsSUFBSyxjQUFBLEdBQUEsT0FBQSxDQUFBLGNBQUEsR0FBZ0IsR0FBckIsQ0FIQTtBQUlBLElBQUssYUFBQSxHQUFBLE9BQUEsQ0FBQSxhQUFBLEdBQWUsRUFBcEIsQ0FKQTtBQUtBLElBQUssV0FBQSxHQUFBLE9BQUEsQ0FBQSxXQUFBLEdBQWEsR0FBbEIsQ0FMQTtPQUFBO09BQUE7T0FBQTtPQUFBO09BQUE7T0FBQTtBQTJDQSxJQUFNLENBQUEsR0FBQSxPQUFBLENBQUEsQ0FBQSxHQUFOLFNBQU0sQ0FBTixDQUFTLENBQVQsRUFDRTtBQUFBLFdBQUMsT0FBQSxDQUFRLEdBQVQsQ0FBYSxDQUFiO0FBQUEsQ0FERixDQTNDQTtBQStDQSxJQUFNLFFBQUEsR0FBQSxPQUFBLENBQUEsUUFBQSxHQUFOLFNBQU0sUUFBTixDQUFnQixDQUFoQixFQUFrQixDQUFsQixFQUNFO0FBQUEsV0FBRyxDQUFHLENBQUgsR0FBSyxDQUFMLENBQUgsR0FBVyxDQUFYO0FBQUEsQ0FERixDQS9DQTtBQWtEQSxJQUFNLFFBQUEsR0FBQSxPQUFBLENBQUEsUUFBQSxHQUFOLFNBQU0sUUFBTixDQUFnQixDQUFoQixFQUFrQixDQUFsQixFQUNFO0FBQUEsV0FBRyxDQUFHLENBQUgsR0FBSyxDQUFMLENBQUgsR0FBVyxDQUFYO0FBQUEsQ0FERixDQWxEQTtB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T0FBbEIsRUFGSTtBQUFBLFlBR0osT0FBQyxRQUFBLENBQVMsTUFBVixDQUFpQixLQUFqQixFQUF1QixNQUF2QixFQUhJO0FBQUEsUyxLQUFOLEMsSUFBQTtBQUFBLEtBREYsQztJQU1DLE1BQUQsRzs7Q0FyQ0YsQ0E3VUE7QUF1WEEsSUFBTSxHQUFBLEdBQUEsT0FBQSxDQUFBLEdBQUEsR0FBTixTQUFNLEdBQU4sR0FDRTtBQUFBLElBQUMsUUFBRCxDQUFXLGFBQVgsRUFBeUIsV0FBekIsRUFBc0MsQ0FBdEM7QUFBQSxJQUNDLFFBQUQsQ0FBVyxZQUFYLEVBQXdCLHNCQUF4QixFQUFpRCxDQUFqRCxFQURBO0FBQUEsSUFFQyxRQUFELENBQVcsWUFBWCxFQUF3QixzQkFBeEIsRUFBaUQsQ0FBakQsRUFGQTtBQUFBLElBR0MsUUFBRCxDQUFXLFlBQVgsRUFBd0Isc0JBQXhCLEVBQWlELENBQWpELEVBSEE7QUFBQSxJQUlDLFFBQUQsQ0FBVyxZQUFYLEVBQXdCLG9CQUF4QixFQUE4QyxDQUE5QyxFQUpBO0FBQUEsSUFLQSxPQUFDLFNBQUQsQ0FBWSxZQUFaLEVBTEE7QUFBQSxDQURGLENBdlhBO0FBbVlDLENBQUQsQ0FBRyxHQUFIIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIjsgQ29uc3RhbnRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWYgd2lkdGggNjEwKVxuKGRlZiBoZWlnaHQgNDAwKVxuKGRlZiB3aXJlZnJhbWUgdHJ1ZSlcbihkZWYgd2lyZWZyYW1lLXdpZHRoIDEuMilcbihkZWYgdGVycmFpbi1oZWlnaHQgNTApXG4oZGVmIHRlcnJhaW4tc2l6ZSAxMDApXG5cbjsgR2VuZXJhbCBVdGlsaXRpZXMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZtYWNybyB3aGVuIFtjb25kaXRpb24gJiBib2R5XVxuICBgKGlmIH5jb25kaXRpb25cbiAgICAgKGRvIH5AYm9keSkpKVxuXG4oZGVmbWFjcm8gZG8tdGltZXMgW3Zhcm5hbWUgbGltaXQgJiBib2R5XVxuICAobGV0IFtlbmQgKGdlbnN5bSldXG4gICAgYChsZXQgW35lbmQgfmxpbWl0XVxuICAgICAgIChsb29wIFt+dmFybmFtZSAwXVxuICAgICAgICAgKHdoZW4gKDwgfnZhcm5hbWUgfmVuZClcbiAgICAgICAgICAgfkBib2R5XG4gICAgICAgICAgIChyZWN1ciAoKyAxIH52YXJuYW1lKSkpKSkpKVxuXG4oZGVmbWFjcm8gZG8tbmVzdGVkIFt4bmFtZSB5bmFtZSB3aWR0aCAmIGJvZHldXG4gIChsZXQgW2l0ZXJhdGlvbnMgKGdlbnN5bSldXG4gICAgYChsZXQgW35pdGVyYXRpb25zIH53aWR0aF1cbiAgICAgICAoZG8tdGltZXMgfnhuYW1lIH5pdGVyYXRpb25zXG4gICAgICAgICAoZG8tdGltZXMgfnluYW1lIH5pdGVyYXRpb25zXG4gICAgICAgICAgIH5AYm9keSkpKSkpXG5cbihkZWZtYWNybyBpbmMhIFtwbGFjZV1cbiAgYChzZXQhIH5wbGFjZSAoKyB+cGxhY2UgMSkpKVxuXG4oZGVmbWFjcm8gYWRkISBbcGxhY2UgYW1vdW50XVxuICBgKHNldCEgfnBsYWNlICgrIH5wbGFjZSB+YW1vdW50KSkpXG5cbihkZWZtYWNybyB0aW1lIFsmIGJvZHldXG4gIChsZXQgW3N0YXJ0IChnZW5zeW0pXG4gICAgICAgIGVuZCAoZ2Vuc3ltKVxuICAgICAgICByZXN1bHQgKGdlbnN5bSldXG4gICAgYChsZXQgW35zdGFydCAoLmdldFRpbWUgKG5ldyBEYXRlKSlcbiAgICAgICAgICAgfnJlc3VsdCAoZG8gfkBib2R5KVxuICAgICAgICAgICB+ZW5kICguZ2V0VGltZSAobmV3IERhdGUpKV1cbiAgICAgICAobCAoKyBcIkVsYXBzZWQgdGltZTogXCIgKC0gfmVuZCB+c3RhcnQpIFwibXMuXCIpKVxuICAgICAgIH5yZXN1bHQpKSlcblxuKGRlZm4gbCBbdl1cbiAgKGNvbnNvbGUubG9nIHYpKVxuXG5cbihkZWZuIG1pZHBvaW50IFthIGJdXG4gICgvICgrIGEgYikgMikpXG5cbihkZWZuIGF2ZXJhZ2UyIFthIGJdXG4gICgvICgrIGEgYikgMikpXG5cbihkZWZuIGF2ZXJhZ2U0IFthIGIgYyBkXVxuICAoLyAoKyBhIGIgYyBkKSA0KSlcblxuKGRlZm4gc2FmZS1hdmVyYWdlIFthIGIgYyBkXVxuICAobGV0IFt0b3RhbCAwIGNvdW50IDBdXG4gICAgKHdoZW4gYSAoYWRkISB0b3RhbCBhKSAoaW5jISBjb3VudCkpXG4gICAgKHdoZW4gYiAoYWRkISB0b3RhbCBiKSAoaW5jISBjb3VudCkpXG4gICAgKHdoZW4gYyAoYWRkISB0b3RhbCBjKSAoaW5jISBjb3VudCkpXG4gICAgKHdoZW4gZCAoYWRkISB0b3RhbCBkKSAoaW5jISBjb3VudCkpXG4gICAgKC8gdG90YWwgY291bnQpKSlcblxuXG4oZGVmbiByYW5kIFtdXG4gIChNYXRoLnJhbmRvbSkpXG5cbihkZWZuIHJhbmQtYXJvdW5kLXplcm8gW3NwcmVhZF1cbiAgKC0gKCogc3ByZWFkIChyYW5kKSAyKSBzcHJlYWQpKVxuXG5cbihkZWZuIGppdHRlciBbdmFsdWUgc3ByZWFkXVxuICAoKyB2YWx1ZSAocmFuZC1hcm91bmQtemVybyBzcHJlYWQpKSlcblxuXG47IEhlaWdodG1hcCBIZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbWFjcm8gaGVpZ2h0bWFwLWdldCBbaG0geCB5XVxuICBgKGFnZXQgfmhtICgrICgqIH55ICguLXJlc29sdXRpb24gfmhtKSkgfngpKSlcblxuKGRlZm4gaGVpZ2h0bWFwLWdldC1zYWZlIFtobSB4IHldXG4gICh3aGVuIChhbmQgKDw9IDAgeCBobS5sYXN0KVxuICAgICAgICAgICAgICg8PSAwIHkgaG0ubGFzdCkpXG4gICAgKGhlaWdodG1hcC1nZXQgaG0geCB5KSkpXG5cbihkZWZtYWNybyBoZWlnaHRtYXAtc2V0ISBbaG0geCB5IHZhbF1cbiAgYChzZXQhIChoZWlnaHRtYXAtZ2V0IH5obSB+eCB+eSkgfnZhbCkpXG5cblxuKGRlZm4gbm9ybWFsaXplIFtobV1cbiAgKGxldCBbbWF4ICgtIEluZmluaXR5KVxuICAgICAgICBtaW4gSW5maW5pdHldXG4gICAgKGRvLXRpbWVzIGkgaG0ubGVuZ3RoXG4gICAgICAobGV0IFtlbCAoYWdldCBobSBpKV1cbiAgICAgICAgKHdoZW4gKDwgbWF4IGVsKSAoc2V0ISBtYXggZWwpKVxuICAgICAgICAod2hlbiAoPiBtaW4gZWwpIChzZXQhIG1pbiBlbCkpKSlcbiAgICAobGV0IFtzcGFuICgtIG1heCBtaW4pXVxuICAgICAgKGRvLXRpbWVzIGkgaG0ubGVuZ3RoXG4gICAgICAgIChzZXQhIChhZ2V0IGhtIGkpXG4gICAgICAgICAgKC8gKC0gKGFnZXQgaG0gaSkgbWluKVxuICAgICAgICAgICAgIHNwYW4pKSkpKSlcblxuKGRlZm4gemVyby1oZWlnaHRtYXAgW2hlaWdodG1hcF1cbiAgKGRvLXRpbWVzIGkgaGVpZ2h0bWFwLmxlbmd0aFxuICAgIChzZXQhIChhZ2V0IGhlaWdodG1hcCBpKSAwLjApKVxuICBoZWlnaHRtYXApXG5cbihkZWZuIG1ha2UtaGVpZ2h0bWFwIFtleHBvbmVudF1cbiAgKGxldCBbcmVzb2x1dGlvbiAoKyAxIChNYXRoLnBvdyAyIGV4cG9uZW50KSldXG4gICAgKGwgKCsgXCJDcmVhdGluZyBcIiByZXNvbHV0aW9uIFwiIGJ5IFwiIHJlc29sdXRpb24gXCIgaGVpZ2h0bWFwLi4uXCIpKVxuICAgIChkZWYgaGVpZ2h0bWFwXG4gICAgICAobmV3IEFycmF5ICgqIHJlc29sdXRpb24gcmVzb2x1dGlvbikpKVxuICAgIChzZXQhIGhlaWdodG1hcC5yZXNvbHV0aW9uIHJlc29sdXRpb24pXG4gICAgKHNldCEgaGVpZ2h0bWFwLmV4cG9uZW50IGV4cG9uZW50KVxuICAgIChzZXQhIGhlaWdodG1hcC5sYXN0ICgtIHJlc29sdXRpb24gMSkpXG4gICAgKHplcm8taGVpZ2h0bWFwIGhlaWdodG1hcCkpKVxuXG5cbjsgUmFuZG9tIE5vaXNlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIHJhbmRvbS1ub2lzZSBbaGVpZ2h0bWFwXVxuICAoZG8tdGltZXMgaSBoZWlnaHRtYXAubGVuZ3RoXG4gICAgKHNldCEgKGFnZXQgaGVpZ2h0bWFwIGkpIChyYW5kKSkpKVxuXG5cbjsgTWlkcG9pbnQgRGlzcGxhY2VtZW50IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIG1wZC1pbml0LWNvcm5lcnMgW2hlaWdodG1hcF1cbiAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCAwIDAgKHJhbmQpKVxuICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIDAgaGVpZ2h0bWFwLmxhc3QgKHJhbmQpKVxuICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGhlaWdodG1hcC5sYXN0IDAgKHJhbmQpKVxuICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGhlaWdodG1hcC5sYXN0IGhlaWdodG1hcC5sYXN0IChyYW5kKSkpXG5cbihkZWZuIG1wZC1kaXNwbGFjZSBbaGVpZ2h0bWFwIGx4IHJ4IGJ5IHR5IHNwcmVhZF1cbiAgKGxldCBbY3ggKG1pZHBvaW50IGx4IHJ4KVxuICAgICAgICBjeSAobWlkcG9pbnQgYnkgdHkpXG5cbiAgICAgICAgYm90dG9tLWxlZnQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIGx4IGJ5KVxuICAgICAgICBib3R0b20tcmlnaHQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIHJ4IGJ5KVxuICAgICAgICB0b3AtbGVmdCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgbHggdHkpXG4gICAgICAgIHRvcC1yaWdodCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgcnggdHkpXG5cbiAgICAgICAgdG9wIChhdmVyYWdlMiB0b3AtbGVmdCB0b3AtcmlnaHQpXG4gICAgICAgIGxlZnQgKGF2ZXJhZ2UyIGJvdHRvbS1sZWZ0IHRvcC1sZWZ0KVxuICAgICAgICBib3R0b20gKGF2ZXJhZ2UyIGJvdHRvbS1sZWZ0IGJvdHRvbS1yaWdodClcbiAgICAgICAgcmlnaHQgKGF2ZXJhZ2UyIGJvdHRvbS1yaWdodCB0b3AtcmlnaHQpXG4gICAgICAgIGNlbnRlciAoYXZlcmFnZTQgdG9wIGxlZnQgYm90dG9tIHJpZ2h0KV1cbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGN4IGJ5IChqaXR0ZXIgYm90dG9tIHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCBjeCB0eSAoaml0dGVyIHRvcCBzcHJlYWQpKVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgbHggY3kgKGppdHRlciBsZWZ0IHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCByeCBjeSAoaml0dGVyIHJpZ2h0IHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCBjeCBjeSAoaml0dGVyIGNlbnRlciBzcHJlYWQpKSkpXG5cbihkZWZuIG1pZHBvaW50LWRpc3BsYWNlbWVudCBbaGVpZ2h0bWFwXVxuICAobXBkLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gIDsgKG1wZC1kaXNwbGFjZSBoZWlnaHRtYXAgMCBoZWlnaHRtYXAubGFzdCAwIGhlaWdodG1hcC5sYXN0IDAuMSlcbiAgKGxvb3AgW2l0ZXIgMFxuICAgICAgICAgc3ByZWFkIDAuM11cbiAgICAod2hlbiAoPCBpdGVyIGhlaWdodG1hcC5leHBvbmVudClcbiAgICAgIChsZXQgW2NodW5rcyAoTWF0aC5wb3cgMiBpdGVyKVxuICAgICAgICAgICAgY2h1bmstd2lkdGggKC8gKC0gaGVpZ2h0bWFwLnJlc29sdXRpb24gMSkgY2h1bmtzKV1cbiAgICAgICAgKGRvLW5lc3RlZCB4Y2h1bmsgeWNodW5rIGNodW5rc1xuICAgICAgICAgIChsZXQgW2xlZnQteCAoKiBjaHVuay13aWR0aCB4Y2h1bmspXG4gICAgICAgICAgICAgICAgcmlnaHQteCAoKyBsZWZ0LXggY2h1bmstd2lkdGgpXG4gICAgICAgICAgICAgICAgYm90dG9tLXkgKCogY2h1bmstd2lkdGggeWNodW5rKVxuICAgICAgICAgICAgICAgIHRvcC15ICgrIGJvdHRvbS15IGNodW5rLXdpZHRoKV1cbiAgICAgICAgICAgIChtcGQtZGlzcGxhY2UgaGVpZ2h0bWFwIGxlZnQteCByaWdodC14IGJvdHRvbS15IHRvcC15IHNwcmVhZCkpKSlcbiAgICAgIChyZWN1ciAoKyAxIGl0ZXIpICgqIHNwcmVhZCAwLjUpKSkpXG4gIChub3JtYWxpemUgaGVpZ2h0bWFwKSlcblxuXG4oZGVmbiBtaWRwb2ludC1kaXNwbGFjZW1lbnQtZmluYWwgW2hlaWdodG1hcF1cbiAgKG1wZC1pbml0LWNvcm5lcnMgaGVpZ2h0bWFwKVxuICA7IChsZXQgW3NwcmVhZCBdKVxuICAobG9vcCBbaXRlciAwXG4gICAgICAgICBzcHJlYWQgKCsgMCAoLnZhbCAoJCBcIiNpbnB1dC1zdGFydGluZy1zcHJlYWRcIikpKV1cbiAgICAod2hlbiAoPCBpdGVyIGhlaWdodG1hcC5leHBvbmVudClcbiAgICAgIChsZXQgW2NodW5rcyAoTWF0aC5wb3cgMiBpdGVyKVxuICAgICAgICAgICAgY2h1bmstd2lkdGggKC8gKC0gaGVpZ2h0bWFwLnJlc29sdXRpb24gMSkgY2h1bmtzKV1cbiAgICAgICAgKGRvLW5lc3RlZCB4Y2h1bmsgeWNodW5rIGNodW5rc1xuICAgICAgICAgIChsZXQgW2xlZnQteCAoKiBjaHVuay13aWR0aCB4Y2h1bmspXG4gICAgICAgICAgICAgICAgcmlnaHQteCAoKyBsZWZ0LXggY2h1bmstd2lkdGgpXG4gICAgICAgICAgICAgICAgYm90dG9tLXkgKCogY2h1bmstd2lkdGggeWNodW5rKVxuICAgICAgICAgICAgICAgIHRvcC15ICgrIGJvdHRvbS15IGNodW5rLXdpZHRoKV1cbiAgICAgICAgICAgIChtcGQtZGlzcGxhY2UgaGVpZ2h0bWFwIGxlZnQteCByaWdodC14IGJvdHRvbS15IHRvcC15IHNwcmVhZCkpKSlcbiAgICAgIChyZWN1ciAoKyAxIGl0ZXIpICgqIHNwcmVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgKCsgMCAoLnZhbCAoJCBcIiNpbnB1dC1zcHJlYWQtcmVkdWN0aW9uXCIpKSkpKSkpXG4gIChub3JtYWxpemUgaGVpZ2h0bWFwKSlcblxuXG4oZGVmbiBtcGQtZGlzcGxhY2UtZDIgW2hlaWdodG1hcCBseCByeCBieSB0eSBzcHJlYWRdXG4gIChsZXQgW2N4IChtaWRwb2ludCBseCByeClcbiAgICAgICAgY3kgKG1pZHBvaW50IGJ5IHR5KVxuXG4gICAgICAgIGJvdHRvbS1sZWZ0IChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCBseCBieSlcbiAgICAgICAgYm90dG9tLXJpZ2h0IChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCByeCBieSlcbiAgICAgICAgdG9wLWxlZnQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIGx4IHR5KVxuICAgICAgICB0b3AtcmlnaHQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIHJ4IHR5KVxuXG4gICAgICAgIHRvcCAoYXZlcmFnZTIgdG9wLWxlZnQgdG9wLXJpZ2h0KVxuICAgICAgICBsZWZ0IChhdmVyYWdlMiBib3R0b20tbGVmdCB0b3AtbGVmdClcbiAgICAgICAgYm90dG9tIChhdmVyYWdlMiBib3R0b20tbGVmdCBib3R0b20tcmlnaHQpXG4gICAgICAgIHJpZ2h0IChhdmVyYWdlMiBib3R0b20tcmlnaHQgdG9wLXJpZ2h0KV1cbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGN4IGJ5IChqaXR0ZXIgYm90dG9tIHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCBjeCB0eSAoaml0dGVyIHRvcCBzcHJlYWQpKVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgbHggY3kgKGppdHRlciBsZWZ0IHNwcmVhZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCByeCBjeSAoaml0dGVyIHJpZ2h0IHNwcmVhZCkpKSlcblxuKGRlZm4gbWlkcG9pbnQtZGlzcGxhY2VtZW50LWQxIFtoZWlnaHRtYXBdXG4gIChtcGQtaW5pdC1jb3JuZXJzIGhlaWdodG1hcCkpXG5cbihkZWZuIG1pZHBvaW50LWRpc3BsYWNlbWVudC1kMiBbaGVpZ2h0bWFwXVxuICAobXBkLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gIChtcGQtZGlzcGxhY2UtZDIgaGVpZ2h0bWFwXG4gICAgICAgICAgICAgICAgICAgMCBoZWlnaHRtYXAubGFzdFxuICAgICAgICAgICAgICAgICAgIDAgaGVpZ2h0bWFwLmxhc3RcbiAgICAgICAgICAgICAgICAgICAwLjEpKVxuXG4oZGVmbiBtaWRwb2ludC1kaXNwbGFjZW1lbnQtZDMgW2hlaWdodG1hcF1cbiAgKG1wZC1pbml0LWNvcm5lcnMgaGVpZ2h0bWFwKVxuICAobXBkLWRpc3BsYWNlIGhlaWdodG1hcFxuICAgICAgICAgICAgICAgIDAgaGVpZ2h0bWFwLmxhc3RcbiAgICAgICAgICAgICAgICAwIGhlaWdodG1hcC5sYXN0XG4gICAgICAgICAgICAgICAgMC4xKSlcblxuXG5cbjsgVGhyZWUuanMgSGVscGVycyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIG1ha2UtZGlyZWN0aW9uYWwtbGlnaHQgW11cbiAgKGxldCBbbGlnaHQgKG5ldyBUSFJFRS5EaXJlY3Rpb25hbExpZ2h0IDB4ZmZmZmZmIDEpXVxuICAgIChsaWdodC5wb3NpdGlvbi5zZXQgMTAwIDAgMTUwKVxuICAgIGxpZ2h0KSlcblxuKGRlZm4gbWFrZS1jYW1lcmEgW11cbiAgKGxldCBbY2FtZXJhIChuZXcgVEhSRUUuUGVyc3BlY3RpdmVDYW1lcmFcbiAgICAgICAgICAgICAgICAgICAgNTUsXG4gICAgICAgICAgICAgICAgICAgICgvIHdpZHRoIGhlaWdodClcbiAgICAgICAgICAgICAgICAgICAgMC4xLFxuICAgICAgICAgICAgICAgICAgICAxMDAwKV1cbiAgICAoY2FtZXJhLnBvc2l0aW9uLnNldCAwIC0xMDAgMTUwKVxuICAgIGNhbWVyYSkpXG5cbihkZWZuIG1ha2UtcmVuZGVyZXIgW11cbiAgKGxldCBbcmVuZGVyZXIgKG5ldyBUSFJFRS5XZWJHTFJlbmRlcmVyIHs6YW50aWFsaWFzIGZhbHNlfSldXG4gICAgKHJlbmRlcmVyLnNldENsZWFyQ29sb3IgMHhmZmZmZmYpXG4gICAgKHJlbmRlcmVyLnNldFNpemUgd2lkdGggaGVpZ2h0KVxuICAgIChyZW5kZXJlci5zZXRQaXhlbFJhdGlvIDIpXG4gICAgcmVuZGVyZXIpKVxuXG4oZGVmbiBtYWtlLWdlb21ldHJ5IFtoZWlnaHRtYXBdXG4gIChsZXQgW2dlb21ldHJ5IChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeVxuICAgICAgICAgICAgICAgICAgICAgIHRlcnJhaW4tc2l6ZVxuICAgICAgICAgICAgICAgICAgICAgIHRlcnJhaW4tc2l6ZVxuICAgICAgICAgICAgICAgICAgICAgICgtIGhlaWdodG1hcC5yZXNvbHV0aW9uIDEpXG4gICAgICAgICAgICAgICAgICAgICAgKC0gaGVpZ2h0bWFwLnJlc29sdXRpb24gMSkpXVxuICAgIChzZXQhIGdlb21ldHJ5LmR5bmFtaWMgdHJ1ZSlcbiAgICBnZW9tZXRyeSkpXG5cbihkZWZuIG1ha2UtY29udHJvbHMgW2NhbWVyYSByZW5kZXJlcl1cbiAgKGxldCBbY29udHJvbHMgKG5ldyBUSFJFRS5UcmFja2JhbGxDb250cm9scyBjYW1lcmEgcmVuZGVyZXIuZG9tRWxlbWVudCldXG4gICAgKHNldCEgY29udHJvbHMucm90YXRlU3BlZWQgMS40KVxuICAgIChzZXQhIGNvbnRyb2xzLnpvb21TcGVlZCAwLjUpXG4gICAgKHNldCEgY29udHJvbHMuc3RhdGljTW92aW5nIHRydWUpXG4gICAgKHNldCEgY29udHJvbHMuZHluYW1pY0RhbXBpbmdGYWN0b3IgMC4zKVxuICAgIGNvbnRyb2xzKSlcblxuKGRlZm4gbWFrZS1wbGFuZSBbZ2VvbWV0cnldXG4gIChsZXQgW21hdGVyaWFsIChuZXcgVEhSRUUuTWVzaExhbWJlcnRNYXRlcmlhbFxuICAgICAgICAgICAgICAgICAgICAgIHs6d2lyZWZyYW1lIHdpcmVmcmFtZVxuICAgICAgICAgICAgICAgICAgICAgICA6d2lyZWZyYW1lTGluZXdpZHRoIHdpcmVmcmFtZS13aWR0aFxuICAgICAgICAgICAgICAgICAgICAgICA6Y29sb3IgMHgwMGJiMDB9KV1cbiAgICAobmV3IFRIUkVFLk1lc2ggZ2VvbWV0cnkgbWF0ZXJpYWwpKSlcblxuXG4oZGVmbiBhdHRhY2gtdG8tZG9tIFtyZW5kZXJlciBlbC1uYW1lIHJlZnJlc2gtZm5dXG4gIChsZXQgW2NvbnRhaW5lciAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQgZWwtbmFtZSlcbiAgICAgICAgc2V0dGluZ3MgKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgXCJkaXZcIilcbiAgICAgICAgcmVmcmVzaC1idXR0b24gKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgXCJidXR0b25cIilcbiAgICAgICAgYnV0dG9uLXRleHQgKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlIFwiUmVmcmVzaFwiKVxuICAgICAgICBjYW5jZWwtc2Nyb2xsIChmbiBbZV0gKC5wcmV2ZW50RGVmYXVsdCBlKSldXG4gICAgKHNldCEgcmVmcmVzaC1idXR0b24ub25jbGljayByZWZyZXNoLWZuKVxuICAgIChzZXQhIHJlbmRlcmVyLmRvbUVsZW1lbnQub25tb3VzZXdoZWVsIGNhbmNlbC1zY3JvbGwpXG4gICAgKHJlbmRlcmVyLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciBcIk1vek1vdXNlUGl4ZWxTY3JvbGxcIiBjYW5jZWwtc2Nyb2xsIGZhbHNlKVxuICAgICguYXBwZW5kQ2hpbGQgcmVmcmVzaC1idXR0b24gYnV0dG9uLXRleHQpXG4gICAgKC5hcHBlbmRDaGlsZCBjb250YWluZXIgcmVuZGVyZXIuZG9tRWxlbWVudClcbiAgICAoLmFwcGVuZENoaWxkIGNvbnRhaW5lciBzZXR0aW5ncylcbiAgICAoLmFwcGVuZENoaWxkIHNldHRpbmdzIHJlZnJlc2gtYnV0dG9uKSkpXG5cbihkZWZuIHVwZGF0ZS1nZW9tZXRyeSBbZ2VvbWV0cnkgaGVpZ2h0bWFwXVxuICAoZG8tdGltZXMgaSBnZW9tZXRyeS52ZXJ0aWNlcy5sZW5ndGhcbiAgICAoc2V0ISAoLi16IChhZ2V0IGdlb21ldHJ5LnZlcnRpY2VzIGkpKVxuICAgICAgKCogdGVycmFpbi1oZWlnaHQgKGFnZXQgaGVpZ2h0bWFwIGkpKSkpXG4gIChzZXQhIGdlb21ldHJ5LnZlcnRpY2VzTmVlZFVwZGF0ZSB0cnVlKVxuICAoZ2VvbWV0cnkuY29tcHV0ZUZhY2VOb3JtYWxzKVxuICAoZ2VvbWV0cnkuY29tcHV0ZVZlcnRleE5vcm1hbHMpXG4gIChnZW9tZXRyeS5jb21wdXRlTW9ycGhOb3JtYWxzKVxuICBnZW9tZXRyeSlcblxuXG47IE1haW4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbiBtYWtlLWRlbW8gW2VsZW1lbnQtaWQgYWxnb3JpdGhtIHNpemVdXG4gIChkZWYgc2NlbmUgKG5ldyBUSFJFRS5TY2VuZSkpXG4gIChzY2VuZS5hZGQgKG5ldyBUSFJFRS5BeGlzSGVscGVyIDEwMCkpXG5cbiAgKGRlZiBjbG9jayAobmV3IFRIUkVFLkNsb2NrKSlcbiAgKGRlZiBjYW1lcmEgKG1ha2UtY2FtZXJhKSlcbiAgKGRlZiByZW5kZXJlciAobWFrZS1yZW5kZXJlcikpXG4gIChkZWYgZ2VvbWV0cnkgKG1ha2UtZ2VvbWV0cnkgKG1ha2UtaGVpZ2h0bWFwIHNpemUpKSlcblxuICAoc2NlbmUuYWRkIChtYWtlLWRpcmVjdGlvbmFsLWxpZ2h0KSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkFtYmllbnRMaWdodCAweGZmZmZmZiAwLjA1KSlcbiAgKHNjZW5lLmFkZCAobWFrZS1wbGFuZSBnZW9tZXRyeSkpXG5cbiAgKGRlZm4gcmVmcmVzaCBbXVxuICAgIChsIFwiUmVmcmVzaGluZyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XCIpXG4gICAgKGxldCBbaGVpZ2h0bWFwIChtYWtlLWhlaWdodG1hcCBzaXplKV1cbiAgICAgIChsIFwiR2VuZXJhdGluZyB0ZXJyYWluLi4uXCIpXG4gICAgICAodGltZSAoYWxnb3JpdGhtIGhlaWdodG1hcCkpXG4gICAgICAobCBcIlJlZnJlc2hpbmcgZ2VvbWV0cnkuLi5cIilcbiAgICAgICh0aW1lICh1cGRhdGUtZ2VvbWV0cnkgZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcbiAgICAgIChsIFwiRG9uZSFcIikpKVxuXG4gIChhdHRhY2gtdG8tZG9tIHJlbmRlcmVyIGVsZW1lbnQtaWQgcmVmcmVzaClcbiAgKGRlZiBjb250cm9scyAobWFrZS1jb250cm9scyBjYW1lcmEgcmVuZGVyZXIpKVxuXG4gIChkZWZuIHJlbmRlciBbXVxuICAgIChsZXQgW2RlbHRhIChjbG9jay5nZXREZWx0YSldXG4gICAgICAocmVxdWVzdEFuaW1hdGlvbkZyYW1lIHJlbmRlcilcbiAgICAgICgudXBkYXRlIGNvbnRyb2xzIGRlbHRhKVxuICAgICAgKHJlbmRlcmVyLnJlbmRlciBzY2VuZSBjYW1lcmEpKSlcblxuICAocmVuZGVyKVxuXG4gIG5pbClcblxuKGRlZm4gbWFrZS1maW5hbCBbZWxlbWVudC1pZF1cbiAgKGRlZiBzY2VuZSAobmV3IFRIUkVFLlNjZW5lKSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkF4aXNIZWxwZXIgMTAwKSlcblxuICAoZGVmIGNsb2NrIChuZXcgVEhSRUUuQ2xvY2spKVxuICAoZGVmIGNhbWVyYSAobWFrZS1jYW1lcmEpKVxuICAoZGVmIHJlbmRlcmVyIChtYWtlLXJlbmRlcmVyKSlcbiAgKGRlZiBoZWlnaHRtYXAgKG1ha2UtaGVpZ2h0bWFwICgudmFsICgkIFwiI2lucHV0LWV4cG9uZW50XCIpKSkpXG4gIChkZWYgZ2VvbWV0cnkgKG1ha2UtZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcbiAgKGRlZiBwbGFuZSAobWFrZS1wbGFuZSBnZW9tZXRyeSkpXG5cbiAgKHNjZW5lLmFkZCAobWFrZS1kaXJlY3Rpb25hbC1saWdodCkpXG4gIChzY2VuZS5hZGQgKG5ldyBUSFJFRS5BbWJpZW50TGlnaHQgMHhmZmZmZmYgMC4wNSkpXG4gIChzY2VuZS5hZGQgcGxhbmUpXG5cbiAgKGRlZm4gcmVmcmVzaCBbXVxuICAgIChsIFwiUmVmcmVzaGluZyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XCIpXG4gICAgKHNjZW5lLnJlbW92ZSBwbGFuZSlcbiAgICAoc2V0ISBoZWlnaHRtYXAgKG1ha2UtaGVpZ2h0bWFwICgudmFsICgkIFwiI2lucHV0LWV4cG9uZW50XCIpKSkpXG4gICAgKHNldCEgZ2VvbWV0cnkgKG1ha2UtZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcbiAgICAoc2V0ISBwbGFuZSAobWFrZS1wbGFuZSBnZW9tZXRyeSkpXG4gICAgKHNjZW5lLmFkZCBwbGFuZSlcbiAgICAobCBcIkdlbmVyYXRpbmcgdGVycmFpbi4uLlwiKVxuICAgICh0aW1lIChtaWRwb2ludC1kaXNwbGFjZW1lbnQtZmluYWwgaGVpZ2h0bWFwKSlcbiAgICAobCBcIlJlZnJlc2hpbmcgZ2VvbWV0cnkuLi5cIilcbiAgICAodGltZSAodXBkYXRlLWdlb21ldHJ5IGdlb21ldHJ5IGhlaWdodG1hcCkpXG4gICAgKGwgXCJEb25lIVwiKSlcblxuICAoYXR0YWNoLXRvLWRvbSByZW5kZXJlciBlbGVtZW50LWlkIHJlZnJlc2gpXG4gIChkZWYgY29udHJvbHMgKG1ha2UtY29udHJvbHMgY2FtZXJhIHJlbmRlcmVyKSlcblxuICAoZGVmbiByZW5kZXIgW11cbiAgICAobGV0IFtkZWx0YSAoY2xvY2suZ2V0RGVsdGEpXVxuICAgICAgKHJlcXVlc3RBbmltYXRpb25GcmFtZSByZW5kZXIpXG4gICAgICAoLnVwZGF0ZSBjb250cm9scyBkZWx0YSlcbiAgICAgIChyZW5kZXJlci5yZW5kZXIgc2NlbmUgY2FtZXJhKSkpXG5cbiAgKHJlbmRlcilcblxuICBuaWwpXG5cblxuKGRlZm4gcnVuIFtdXG4gIChtYWtlLWRlbW8gXCJkZW1vLXJhbmRvbVwiIHJhbmRvbS1ub2lzZSA3KVxuICAobWFrZS1kZW1vIFwiZGVtby1tcGQtMVwiIG1pZHBvaW50LWRpc3BsYWNlbWVudC1kMSAyKVxuICAobWFrZS1kZW1vIFwiZGVtby1tcGQtMlwiIG1pZHBvaW50LWRpc3BsYWNlbWVudC1kMiAyKVxuICAobWFrZS1kZW1vIFwiZGVtby1tcGQtM1wiIG1pZHBvaW50LWRpc3BsYWNlbWVudC1kMyAyKVxuICAobWFrZS1kZW1vIFwiZGVtby1tcGQtNFwiIG1pZHBvaW50LWRpc3BsYWNlbWVudCAzKVxuICAobWFrZS1maW5hbCBcImRlbW8tZmluYWxcIilcbiAgOyAobWFrZS1kZW1vIFwiZGVtby1taWRwb2ludFwiIG1pZHBvaW50LWRpc3BsYWNlbWVudClcbiAgOyAobWFrZS1kZW1vIFwiZGVtby1kaWFtb25kXCIgZGlhbW9uZC1zcXVhcmUpXG5cbiAgKVxuXG4oJCBydW4pXG5cblxuOyB2aW06IGx3Kz1kby10aW1lcyBsdys9ZG8tbmVzdGVkIDpcbiJdfQ==
--- a/media/js/terrain2.js	Mon Mar 07 13:44:20 2016 +0000
+++ b/media/js/terrain2.js	Sat Jun 25 15:57:05 2016 +0000
@@ -780,4 +780,5 @@
 
 module.exports = wrappedNDArrayCtor
 
-},{"iota-array":2,"is-buffer":3}]},{},[1]);
+},{"iota-array":2,"is-buffer":3}]},{},[1])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm1lZGlhL2pzL3dpc3AvYW5vbnltb3VzLndpc3AiLCJub2RlX21vZHVsZXMvaW90YS1hcnJheS9pb3RhLmpzIiwibm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9uZGFycmF5L25kYXJyYXkuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0lDQUEsSUFBQyxJLEdBQUQ7QUFBQSxRQUFBLEUsRUFBSSxNQUFKO0FBQUEsUUFBQSxHLEVBQUEsSyxDQUFBO0FBQUEsTTs7O0FBSUEsSUFBSyxLQUFBLEdBQUEsT0FBQSxDQUFBLEtBQUEsR0FBTSxHQUFYLEM7QUFDQSxJQUFLLE1BQUEsR0FBQSxPQUFBLENBQUEsTUFBQSxHQUFPLEdBQVosQztBQUNBLElBQUssU0FBQSxHQUFBLE9BQUEsQ0FBQSxTQUFBLEcsSUFBTCxDO0FBQ0EsSUFBSyxjQUFBLEdBQUEsT0FBQSxDQUFBLGNBQUEsR0FBZ0IsR0FBckIsQztBQUNBLElBQUssYUFBQSxHQUFBLE9BQUEsQ0FBQSxhQUFBLEdBQWUsRUFBcEIsQztBQUNBLElBQUssV0FBQSxHQUFBLE9BQUEsQ0FBQSxXQUFBLEdBQWEsR0FBbEIsQzs7OztBQW9CQSxJQUFNLEdBQUEsR0FBQSxPQUFBLENBQUEsR0FBQSxHQUFOLFNBQU0sR0FBTixDQUFXLENBQVgsRUFDRTtBQUFBLFdBQUcsQ0FBSCxHQUFLLENBQUw7QUFBQSxDQURGLEM7QUFHQSxJQUFNLEdBQUEsR0FBQSxPQUFBLENBQUEsR0FBQSxHQUFOLFNBQU0sR0FBTixDQUFXLENBQVgsRUFDRTtBQUFBLFdBQUcsQ0FBSCxHQUFLLENBQUw7QUFBQSxDQURGLEM7Ozs7Ozs7OztBQXdFQSxJQUFNLFFBQUEsR0FBQSxPQUFBLENBQUEsUUFBQSxHQUFOLFNBQU0sUUFBTixD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QUFELENBQVksWUFBWjtBQUFBLENBREYsQztBQUdDLENBQUQsQ0FBRyxHQUFIOzs7O0FDcFhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIihucyBkZW1vXG4gICg6cmVxdWlyZSBbbmRhcnJheV0pKVxuXG47IENvbnN0YW50cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmIHdpZHRoIDYxMClcbihkZWYgaGVpZ2h0IDQwMClcbihkZWYgd2lyZWZyYW1lIHRydWUpXG4oZGVmIHdpcmVmcmFtZS13aWR0aCAxLjIpXG4oZGVmIHRlcnJhaW4taGVpZ2h0IDUwKVxuKGRlZiB0ZXJyYWluLXNpemUgMTAwKVxuXG47IEdlbmVyYWwgVXRpbGl0aWVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbWFjcm8gd2hlbiBbY29uZGl0aW9uICYgYm9keV1cbiAgYChpZiB+Y29uZGl0aW9uXG4gICAgIChkbyB+QGJvZHkpKSlcblxuKGRlZm1hY3JvIHdoZW4tbm90IFtjb25kaXRpb24gJiBib2R5XVxuICBgKHdoZW4gKG5vdCB+Y29uZGl0aW9uKVxuICAgICB+QGJvZHkpKVxuXG4oZGVmbWFjcm8gLT4gWyYgb3BlcmF0aW9uc11cbiAgKHJlZHVjZVxuICAgIChmbiBbZm9ybSBvcGVyYXRpb25dXG4gICAgICAoY29ucyAoZmlyc3Qgb3BlcmF0aW9uKVxuICAgICAgICAgICAgKGNvbnMgZm9ybSAocmVzdCBvcGVyYXRpb24pKSkpXG4gICAgKGZpcnN0IG9wZXJhdGlvbnMpXG4gICAgKHJlc3Qgb3BlcmF0aW9ucykpKVxuXG5cbihkZWZuIGluYyBbeF1cbiAgKCsgeCAxKSlcblxuKGRlZm4gZGVjIFt4XVxuICAoLSB4IDEpKVxuXG5cbihkZWZtYWNybyBkby10aW1lcyBbdmFybmFtZSBsaW1pdCAmIGJvZHldXG4gIChsZXQgW2VuZCAoZ2Vuc3ltKV1cbiAgICBgKGxldCBbfmVuZCB+bGltaXRdXG4gICAgICAgKGxvb3AgW352YXJuYW1lIDBdXG4gICAgICAgICAod2hlbiAoPCB+dmFybmFtZSB+ZW5kKVxuICAgICAgICAgICB+QGJvZHlcbiAgICAgICAgICAgKHJlY3VyIChpbmMgfnZhcm5hbWUpKSkpKSkpXG5cbihkZWZtYWNybyBkby1zdHJpZGUgW3Zhcm5hbWVzIHN0YXJ0LWZvcm0gZW5kLWZvcm0gc3RyaWRlLWZvcm0gJiBib2R5XVxuICAobGV0IFtzdHJpZGUgKGdlbnN5bSBcInN0cmlkZVwiKVxuICAgICAgICBzdGFydCAoZ2Vuc3ltIFwic3RhcnRcIilcbiAgICAgICAgZW5kIChnZW5zeW0gXCJlbmRcIilcbiAgICAgICAgYnVpbGQgKGZuIGJ1aWxkIFt2YXJzXVxuICAgICAgICAgICAgICAgIChpZiAoZW1wdHk/IHZhcnMpXG4gICAgICAgICAgICAgICAgICBgKGRvIH5AYm9keSlcbiAgICAgICAgICAgICAgICAgIChsZXQgW3Zhcm5hbWUgKGZpcnN0IHZhcnMpXVxuICAgICAgICAgICAgICAgICAgICBgKGxvb3AgW352YXJuYW1lIH5zdGFydF1cbiAgICAgICAgICAgICAgICAgICAgICAgKHdoZW4gKDwgfnZhcm5hbWUgfmVuZClcbiAgICAgICAgICAgICAgICAgICAgICAgICB+KGJ1aWxkIChyZXN0IHZhcnMpKVxuICAgICAgICAgICAgICAgICAgICAgICAgIChyZWN1ciAoKyB+dmFybmFtZSB+c3RyaWRlKSkpKSkpKV1cbiAgICA7IEZpeCB0aGUgbnVtYmVycyBvbmNlIG91dHNpZGUgdGhlIG5lc3RlZCBsb29wcyxcbiAgICA7IGFuZCB0aGVuIGJ1aWxkIHRoZSBndXRzLlxuICAgIGAobGV0IFt+c3RhcnQgfnN0YXJ0LWZvcm1cbiAgICAgICAgICAgfmVuZCB+ZW5kLWZvcm1cbiAgICAgICAgICAgfnN0cmlkZSB+c3RyaWRlLWZvcm1dXG4gICAgICAgfihidWlsZCB2YXJuYW1lcykpKSlcblxuXG4oZGVmbWFjcm8gZG8tbmRhcnJheSBbdmFycyBhcnJheS1mb3JtICYgYm9keV1cbiAgKGxldCBbYXJyYXktdmFyIChnZW5zeW0gXCJhcnJheVwiKVxuICAgICAgICBidWlsZCAoZm4gYnVpbGQgW3ZhcnMgbl1cbiAgICAgICAgICAgICAgICAoaWYgKGVtcHR5PyB2YXJzKVxuICAgICAgICAgICAgICAgICAgYChkbyB+QGJvZHkpXG4gICAgICAgICAgICAgICAgICBgKGRvLXRpbWVzIH4oZmlyc3QgdmFycykgKGFnZXQgKC4tc2hhcGUgfmFycmF5LXZhcikgfm4pXG4gICAgICAgICAgICAgICAgICAgICB+KGJ1aWxkIChyZXN0IHZhcnMpIChpbmMgbikpKSkpXVxuICAgIGAobGV0IFt+YXJyYXktdmFyIH5hcnJheS1mb3JtXVxuICAgICAgIH4oYnVpbGQgdmFycyAwKSkpKVxuXG4oZGVmbWFjcm8gZG8tbmRhcnJheS1lbCBbZWxlbWVudCBhcnJheS1mb3JtICYgYm9keV1cbiAgKGxldCBbaW5kZXggKGdlbnN5bSBcImluZGV4XCIpXG4gICAgICAgIGFycmF5IChnZW5zeW0gXCJhcnJheVwiKV1cbiAgICBgKGxldCBbfmFycmF5IH5hcnJheS1mb3JtXVxuICAgICAgIChkby10aW1lcyB+aW5kZXggKC4tbGVuZ3RoICguLWRhdGEgfmFycmF5KSlcbiAgICAgICAgIChsZXQgW35lbGVtZW50IChhZ2V0ICguLWRhdGEgfmFycmF5KSB+aW5kZXgpXVxuICAgICAgICAgICB+QGJvZHkpKSkpKVxuXG5cbihkZWZtYWNybyBpbmMhIFtwbGFjZV1cbiAgYChzZXQhIH5wbGFjZSAoaW5jIH5wbGFjZSkpKVxuXG4oZGVmbWFjcm8gYWRkISBbcGxhY2UgYW1vdW50XVxuICBgKHNldCEgfnBsYWNlICgrIH5wbGFjZSB+YW1vdW50KSkpXG5cblxuKGRlZm1hY3JvIGwgWyYgZm9ybXNdXG4gIGAoY29uc29sZS5sb2cgfkBmb3JtcykpXG5cbihkZWZtYWNybyB0aW1lIFsmIGJvZHldXG4gIChsZXQgW3N0YXJ0IChnZW5zeW0pXG4gICAgICAgIGVuZCAoZ2Vuc3ltKVxuICAgICAgICByZXN1bHQgKGdlbnN5bSldXG4gICAgYChsZXQgW35zdGFydCAoLmdldFRpbWUgKG5ldyBEYXRlKSlcbiAgICAgICAgICAgfnJlc3VsdCAoZG8gfkBib2R5KVxuICAgICAgICAgICB+ZW5kICguZ2V0VGltZSAobmV3IERhdGUpKV1cbiAgICAgICAobCAoKyBcIkVsYXBzZWQgdGltZTogXCIgKC0gfmVuZCB+c3RhcnQpIFwibXMuXCIpKVxuICAgICAgIH5yZXN1bHQpKSlcblxuXG4oZGVmbiBtaWRwb2ludCBbYSBiXVxuICAoLyAoKyBhIGIpIDIpKVxuXG4oZGVmbiBhdmVyYWdlMiBbYSBiXVxuICAoLyAoKyBhIGIpIDIpKVxuXG4oZGVmbiBhdmVyYWdlNCBbYSBiIGMgZF1cbiAgKC8gKCsgYSBiIGMgZCkgNCkpXG5cbihkZWZuIHNhZmUtYXZlcmFnZSBbYSBiIGMgZF1cbiAgKGxldCBbdG90YWwgMCBjb3VudCAwXVxuICAgICh3aGVuIGEgKGFkZCEgdG90YWwgYSkgKGluYyEgY291bnQpKVxuICAgICh3aGVuIGIgKGFkZCEgdG90YWwgYikgKGluYyEgY291bnQpKVxuICAgICh3aGVuIGMgKGFkZCEgdG90YWwgYykgKGluYyEgY291bnQpKVxuICAgICh3aGVuIGQgKGFkZCEgdG90YWwgZCkgKGluYyEgY291bnQpKVxuICAgICgvIHRvdGFsIGNvdW50KSkpXG5cblxuOyBSYW5kb21uZXNzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gcmFuZCBbXVxuICAoTWF0aC5yYW5kb20pKVxuXG4oZGVmbiByYW5kLWFyb3VuZC16ZXJvIFtzcHJlYWRdXG4gICgtICgqIHNwcmVhZCAocmFuZCkgMikgc3ByZWFkKSlcblxuKGRlZm4gaml0dGVyIFt2YWx1ZSBzcHJlYWRdXG4gICgrIHZhbHVlIChyYW5kLWFyb3VuZC16ZXJvIHNwcmVhZCkpKVxuXG5cbjsgSGVpZ2h0bWFwIEhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIGhlaWdodG1hcC1yZXNvbHV0aW9uIFtoZWlnaHRtYXBdXG4gIChhZ2V0IGhlaWdodG1hcC5zaGFwZSAwKSlcblxuKGRlZm4gaGVpZ2h0bWFwLWxhc3QtaW5kZXggW2hlaWdodG1hcF1cbiAgKGRlYyAoaGVpZ2h0bWFwLXJlc29sdXRpb24gaGVpZ2h0bWFwKSkpXG5cbihkZWZuIGhlaWdodG1hcC1jZW50ZXItaW5kZXggW2hlaWdodG1hcF1cbiAgKG1pZHBvaW50IDAgKGhlaWdodG1hcC1sYXN0LWluZGV4IGhlaWdodG1hcCkpKVxuXG5cbihkZWZuIGhlaWdodG1hcC1nZXQgW2hlaWdodG1hcCB4IHldXG4gICguZ2V0IGhlaWdodG1hcCB4IHkpKVxuXG4oZGVmbiBoZWlnaHRtYXAtZ2V0LXNhZmUgW2hlaWdodG1hcCB4IHldXG4gIChsZXQgW2xhc3QgKGhlaWdodG1hcC1sYXN0LWluZGV4IGhlaWdodG1hcCldXG4gICAgKHdoZW4gKGFuZCAoPD0gMCB4IGxhc3QpXG4gICAgICAgICAgICAgICAoPD0gMCB5IGxhc3QpKVxuICAgICAgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIHggeSkpKSlcblxuKGRlZm4gaGVpZ2h0bWFwLXNldCEgW2hlaWdodG1hcCB4IHkgdmFsXVxuICAoLnNldCBoZWlnaHRtYXAgeCB5IHZhbCkpXG5cbihkZWZuIGhlaWdodG1hcC1zZXQtaWYtdW5zZXQhIFtoZWlnaHRtYXAgeCB5IHZhbF1cbiAgKHdoZW4gKD09IDAgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIHggeSkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCB4IHkgdmFsKSkpXG5cblxuKGRlZm4gbm9ybWFsaXplIFtoZWlnaHRtYXBdXG4gIChsZXQgW21heCAoLSBJbmZpbml0eSlcbiAgICAgICAgbWluIEluZmluaXR5XVxuICAgIChkby1uZGFycmF5LWVsIGVsIGhlaWdodG1hcFxuICAgICAgKHdoZW4gKDwgbWF4IGVsKSAoc2V0ISBtYXggZWwpKVxuICAgICAgKHdoZW4gKD4gbWluIGVsKSAoc2V0ISBtaW4gZWwpKSlcbiAgICAobGV0IFtzcGFuICgtIG1heCBtaW4pXVxuICAgICAgKGRvLW5kYXJyYXkgW3ggeV0gaGVpZ2h0bWFwXG4gICAgICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgeCB5XG4gICAgICAgICAgICAgICAgICAgICAgICAoLyAoLSAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgeCB5KSBtaW4pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFuKSkpKSkpXG5cblxuKGRlZm4gbWFrZS1oZWlnaHRtYXAgW2V4cG9uZW50XVxuICAobGV0IFtyZXNvbHV0aW9uICgrIChNYXRoLnBvdyAyIGV4cG9uZW50KSAxKV1cbiAgICAobGV0IFtoZWlnaHRtYXAgKG5kYXJyYXkgKG5ldyBGbG9hdDY0QXJyYXkgKCogcmVzb2x1dGlvbiByZXNvbHV0aW9uKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3Jlc29sdXRpb24gcmVzb2x1dGlvbl0pXVxuICAgICAgKHNldCEgaGVpZ2h0bWFwLmV4cG9uZW50IGV4cG9uZW50KVxuICAgICAgKHNldCEgaGVpZ2h0bWFwLnJlc29sdXRpb24gcmVzb2x1dGlvbilcbiAgICAgIChzZXQhIGhlaWdodG1hcC5sYXN0IChkZWMgcmVzb2x1dGlvbikpXG4gICAgICBoZWlnaHRtYXApKSlcblxuXG4oZGVmbiB0b3AtbGVmdC1jb3JuZXIgW2hlaWdodG1hcF1cbiAgKGxldCBbY2VudGVyIChoZWlnaHRtYXAtY2VudGVyLWluZGV4IGhlaWdodG1hcCldXG4gICAgKC0+IGhlaWdodG1hcFxuICAgICAgKC5sbyAwIDApXG4gICAgICAoLmhpIChpbmMgY2VudGVyKSAoaW5jIGNlbnRlcikpKSkpXG5cbihkZWZuIHRvcC1yaWdodC1jb3JuZXIgW2hlaWdodG1hcF1cbiAgKGxldCBbY2VudGVyIChoZWlnaHRtYXAtY2VudGVyLWluZGV4IGhlaWdodG1hcCldXG4gICAgKC0+IGhlaWdodG1hcFxuICAgICAgKC5sbyBjZW50ZXIgMClcbiAgICAgICguaGkgKGluYyBjZW50ZXIpIChpbmMgY2VudGVyKSkpKSlcblxuKGRlZm4gYm90dG9tLWxlZnQtY29ybmVyIFtoZWlnaHRtYXBdXG4gIChsZXQgW2NlbnRlciAoaGVpZ2h0bWFwLWNlbnRlci1pbmRleCBoZWlnaHRtYXApXVxuICAgICgtPiBoZWlnaHRtYXBcbiAgICAgICgubG8gMCBjZW50ZXIpXG4gICAgICAoLmhpIChpbmMgY2VudGVyKSAoaW5jIGNlbnRlcikpKSkpXG5cbihkZWZuIGJvdHRvbS1yaWdodC1jb3JuZXIgW2hlaWdodG1hcF1cbiAgKGxldCBbY2VudGVyIChoZWlnaHRtYXAtY2VudGVyLWluZGV4IGhlaWdodG1hcCldXG4gICAgKC0+IGhlaWdodG1hcFxuICAgICAgKC5sbyBjZW50ZXIgY2VudGVyKVxuICAgICAgKC5oaSAoaW5jIGNlbnRlcikgKGluYyBjZW50ZXIpKSkpKVxuXG5cbjsgTWlkcG9pbnQgRGlzcGxhY2VtZW50IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIG1wZC1pbml0LWNvcm5lcnMgW2hlaWdodG1hcF1cbiAgKGxldCBbbGFzdCAoaGVpZ2h0bWFwLWxhc3QtaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIDAgICAgMCAgICAocmFuZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCAwICAgIGxhc3QgKHJhbmQpKVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgbGFzdCAwICAgIChyYW5kKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGxhc3QgbGFzdCAocmFuZCkpKSlcblxuKGRlZm4gbXBkLWRpc3BsYWNlIFtoZWlnaHRtYXAgc3ByZWFkIHNwcmVhZC1yZWR1Y3Rpb25dXG4gIChsZXQgW2xhc3QgKGhlaWdodG1hcC1sYXN0LWluZGV4IGhlaWdodG1hcClcbiAgICAgICAgYyAobWlkcG9pbnQgMCBsYXN0KVxuXG4gICAgICAgIGJvdHRvbS1sZWZ0ICAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgMCAgICAwKVxuICAgICAgICBib3R0b20tcmlnaHQgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIGxhc3QgMClcbiAgICAgICAgdG9wLWxlZnQgICAgIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCAwICAgIGxhc3QpXG4gICAgICAgIHRvcC1yaWdodCAgICAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgbGFzdCBsYXN0KVxuXG4gICAgICAgIHRvcCAgICAoYXZlcmFnZTIgdG9wLWxlZnQgdG9wLXJpZ2h0KVxuICAgICAgICBsZWZ0ICAgKGF2ZXJhZ2UyIGJvdHRvbS1sZWZ0IHRvcC1sZWZ0KVxuICAgICAgICBib3R0b20gKGF2ZXJhZ2UyIGJvdHRvbS1sZWZ0IGJvdHRvbS1yaWdodClcbiAgICAgICAgcmlnaHQgIChhdmVyYWdlMiBib3R0b20tcmlnaHQgdG9wLXJpZ2h0KVxuICAgICAgICBjZW50ZXIgKGF2ZXJhZ2U0IHRvcCBsZWZ0IGJvdHRvbSByaWdodClcblxuICAgICAgICBuZXh0LXNwcmVhZCAoKiBzcHJlYWQgc3ByZWFkLXJlZHVjdGlvbildXG4gICAgKGhlaWdodG1hcC1zZXQtaWYtdW5zZXQhIGhlaWdodG1hcCBjICAgIDAgICAgKGppdHRlciBib3R0b20gc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldC1pZi11bnNldCEgaGVpZ2h0bWFwIGMgICAgbGFzdCAoaml0dGVyIHRvcCBzcHJlYWQpKVxuICAgIChoZWlnaHRtYXAtc2V0LWlmLXVuc2V0ISBoZWlnaHRtYXAgMCAgICBjICAgIChqaXR0ZXIgbGVmdCBzcHJlYWQpKVxuICAgIChoZWlnaHRtYXAtc2V0LWlmLXVuc2V0ISBoZWlnaHRtYXAgbGFzdCBjICAgIChqaXR0ZXIgcmlnaHQgc3ByZWFkKSlcbiAgICAoaGVpZ2h0bWFwLXNldC1pZi11bnNldCEgaGVpZ2h0bWFwIGMgICAgYyAgICAoaml0dGVyIGNlbnRlciBzcHJlYWQpKVxuICAgICh3aGVuLW5vdCAoPT0gMyAoaGVpZ2h0bWFwLXJlc29sdXRpb24gaGVpZ2h0bWFwKSlcbiAgICAgIChtcGQtZGlzcGxhY2UgKHRvcC1sZWZ0LWNvcm5lciBoZWlnaHRtYXApIG5leHQtc3ByZWFkIHNwcmVhZC1yZWR1Y3Rpb24pXG4gICAgICAobXBkLWRpc3BsYWNlICh0b3AtcmlnaHQtY29ybmVyIGhlaWdodG1hcCkgbmV4dC1zcHJlYWQgc3ByZWFkLXJlZHVjdGlvbilcbiAgICAgIChtcGQtZGlzcGxhY2UgKGJvdHRvbS1sZWZ0LWNvcm5lciBoZWlnaHRtYXApIG5leHQtc3ByZWFkIHNwcmVhZC1yZWR1Y3Rpb24pXG4gICAgICAobXBkLWRpc3BsYWNlIChib3R0b20tcmlnaHQtY29ybmVyIGhlaWdodG1hcCkgbmV4dC1zcHJlYWQgc3ByZWFkLXJlZHVjdGlvbikpKSlcblxuKGRlZm4gbWlkcG9pbnQtZGlzcGxhY2VtZW50IFtoZWlnaHRtYXBdXG4gIChsZXQgW2luaXRpYWwtc3ByZWFkIDAuMyBcbiAgICAgICAgc3ByZWFkLXJlZHVjdGlvbiAwLjU1XVxuICAgIChtcGQtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgICAobXBkLWRpc3BsYWNlIGhlaWdodG1hcCBpbml0aWFsLXNwcmVhZCBzcHJlYWQtcmVkdWN0aW9uKVxuICAgIChub3JtYWxpemUgaGVpZ2h0bWFwKSkpXG5cblxuOyBUaHJlZS5qcyBIZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gbWFrZS1kaXJlY3Rpb25hbC1saWdodCBbXVxuICAobGV0IFtsaWdodCAobmV3IFRIUkVFLkRpcmVjdGlvbmFsTGlnaHQgMHhmZmZmZmYgMSldXG4gICAgKGxpZ2h0LnBvc2l0aW9uLnNldCAxMDAgMCAxNTApXG4gICAgbGlnaHQpKVxuXG4oZGVmbiBtYWtlLWNhbWVyYSBbXVxuICAobGV0IFtjYW1lcmEgKG5ldyBUSFJFRS5QZXJzcGVjdGl2ZUNhbWVyYVxuICAgICAgICAgICAgICAgICAgICA1NSxcbiAgICAgICAgICAgICAgICAgICAgKC8gd2lkdGggaGVpZ2h0KVxuICAgICAgICAgICAgICAgICAgICAwLjEsXG4gICAgICAgICAgICAgICAgICAgIDEwMDApXVxuICAgIChjYW1lcmEucG9zaXRpb24uc2V0IDAgLTEwMCAxNTApXG4gICAgY2FtZXJhKSlcblxuKGRlZm4gbWFrZS1yZW5kZXJlciBbXVxuICAobGV0IFtyZW5kZXJlciAobmV3IFRIUkVFLldlYkdMUmVuZGVyZXIgezphbnRpYWxpYXMgZmFsc2V9KV1cbiAgICAocmVuZGVyZXIuc2V0Q2xlYXJDb2xvciAweGZmZmZmZilcbiAgICAocmVuZGVyZXIuc2V0U2l6ZSB3aWR0aCBoZWlnaHQpXG4gICAgKHJlbmRlcmVyLnNldFBpeGVsUmF0aW8gMilcbiAgICByZW5kZXJlcikpXG5cbihkZWZuIG1ha2UtZ2VvbWV0cnkgW2hlaWdodG1hcF1cbiAgKGxldCBbcmVzb2x1dGlvbiAoYWdldCBoZWlnaHRtYXAuc2hhcGUgMClcbiAgICAgICAgZ2VvbWV0cnkgKG5ldyBUSFJFRS5QbGFuZUdlb21ldHJ5XG4gICAgICAgICAgICAgICAgICAgICAgdGVycmFpbi1zaXplXG4gICAgICAgICAgICAgICAgICAgICAgdGVycmFpbi1zaXplXG4gICAgICAgICAgICAgICAgICAgICAgKC0gcmVzb2x1dGlvbiAxKVxuICAgICAgICAgICAgICAgICAgICAgICgtIHJlc29sdXRpb24gMSkpXVxuICAgIGdlb21ldHJ5KSlcblxuKGRlZm4gbWFrZS1jb250cm9scyBbY2FtZXJhIHJlbmRlcmVyXVxuICAobGV0IFtjb250cm9scyAobmV3IFRIUkVFLlRyYWNrYmFsbENvbnRyb2xzIGNhbWVyYSByZW5kZXJlci5kb21FbGVtZW50KV1cbiAgICAoc2V0ISBjb250cm9scy5yb3RhdGVTcGVlZCAxLjQpXG4gICAgKHNldCEgY29udHJvbHMuem9vbVNwZWVkIDAuNSlcbiAgICAoc2V0ISBjb250cm9scy5zdGF0aWNNb3ZpbmcgdHJ1ZSlcbiAgICAoc2V0ISBjb250cm9scy5keW5hbWljRGFtcGluZ0ZhY3RvciAwLjMpXG4gICAgY29udHJvbHMpKVxuXG4oZGVmbiBtYWtlLXBsYW5lIFtnZW9tZXRyeV1cbiAgKGxldCBbbWF0ZXJpYWwgKG5ldyBUSFJFRS5NZXNoTGFtYmVydE1hdGVyaWFsXG4gICAgICAgICAgICAgICAgICAgICAgezp3aXJlZnJhbWUgd2lyZWZyYW1lXG4gICAgICAgICAgICAgICAgICAgICAgIDp3aXJlZnJhbWVMaW5ld2lkdGggd2lyZWZyYW1lLXdpZHRoXG4gICAgICAgICAgICAgICAgICAgICAgIDpjb2xvciAweDAwYmIwMH0pXVxuICAgIChuZXcgVEhSRUUuTWVzaCBnZW9tZXRyeSBtYXRlcmlhbCkpKVxuXG5cbihkZWZuIGF0dGFjaC10by1kb20gW3JlbmRlcmVyIGVsLW5hbWUgcmVmcmVzaC1mbl1cbiAgKGxldCBbY29udGFpbmVyIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCBlbC1uYW1lKVxuICAgICAgICBzZXR0aW5ncyAoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBcImRpdlwiKVxuICAgICAgICByZWZyZXNoLWJ1dHRvbiAoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBcImJ1dHRvblwiKVxuICAgICAgICBidXR0b24tdGV4dCAoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUgXCJSZWZyZXNoXCIpXG4gICAgICAgIGNhbmNlbC1zY3JvbGwgKGZuIFtlXSAoLnByZXZlbnREZWZhdWx0IGUpKV1cbiAgICAoc2V0ISByZWZyZXNoLWJ1dHRvbi5vbmNsaWNrIHJlZnJlc2gtZm4pXG4gICAgKHNldCEgcmVuZGVyZXIuZG9tRWxlbWVudC5vbm1vdXNld2hlZWwgY2FuY2VsLXNjcm9sbClcbiAgICAocmVuZGVyZXIuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyIFwiTW96TW91c2VQaXhlbFNjcm9sbFwiIGNhbmNlbC1zY3JvbGwgZmFsc2UpXG4gICAgKC5hcHBlbmRDaGlsZCByZWZyZXNoLWJ1dHRvbiBidXR0b24tdGV4dClcbiAgICAoLmFwcGVuZENoaWxkIGNvbnRhaW5lciByZW5kZXJlci5kb21FbGVtZW50KVxuICAgICguYXBwZW5kQ2hpbGQgY29udGFpbmVyIHNldHRpbmdzKVxuICAgICguYXBwZW5kQ2hpbGQgc2V0dGluZ3MgcmVmcmVzaC1idXR0b24pKSlcblxuXG4oZGVmbiB1cGRhdGUtZ2VvbWV0cnkgW2dlb21ldHJ5IGhlaWdodG1hcF1cbiAgKGxvb3AgW2kgMF1cbiAgICAoaWYgKDwgaSBnZW9tZXRyeS52ZXJ0aWNlcy5sZW5ndGgpXG4gICAgICAoZG8gKHNldCEgKC4teiAoYWdldCBnZW9tZXRyeS52ZXJ0aWNlcyBpKSlcbiAgICAgICAgICAgICAgICAoKiB0ZXJyYWluLWhlaWdodCAoYWdldCAoLi1kYXRhIGhlaWdodG1hcCkgaSkpKVxuICAgICAgICAocmVjdXIgKCsgaSAxKSkpKSlcbiAgKGdlb21ldHJ5LmNvbXB1dGVWZXJ0ZXhOb3JtYWxzKVxuICBnZW9tZXRyeSlcblxuXG47IE1haW4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbiBtYWtlLWZpbmFsIFtlbGVtZW50LWlkXVxuICAoZGVmIHNjZW5lIChuZXcgVEhSRUUuU2NlbmUpKVxuICAoc2NlbmUuYWRkIChuZXcgVEhSRUUuQXhpc0hlbHBlciAxMDApKVxuXG4gIChkZWYgY2xvY2sgKG5ldyBUSFJFRS5DbG9jaykpXG4gIChkZWYgY2FtZXJhIChtYWtlLWNhbWVyYSkpXG4gIChkZWYgcmVuZGVyZXIgKG1ha2UtcmVuZGVyZXIpKVxuXG4gIChkZWYgZ2VvbWV0cnkpXG4gIChkZWYgcGxhbmUpXG5cbiAgKHNjZW5lLmFkZCAobWFrZS1kaXJlY3Rpb25hbC1saWdodCkpXG4gIChzY2VuZS5hZGQgKG5ldyBUSFJFRS5BbWJpZW50TGlnaHQgMHhmZmZmZmYgMC4wNSkpXG5cbiAgKGRlZm4gcmVmcmVzaCBbXVxuICAgIChsZXQgW2hlaWdodG1hcCAobWFrZS1oZWlnaHRtYXAgNildXG4gICAgICAobCBcIkdlbmVyYXRpbmcgdGVycmFpbi4uLlwiKVxuICAgICAgKHRpbWUgKG1pZHBvaW50LWRpc3BsYWNlbWVudCBoZWlnaHRtYXApKVxuXG4gICAgICAobCBcIlJlYnVpbGRpbmcgZ2VvbWV0cnkuLi5cIilcbiAgICAgICh0aW1lXG4gICAgICAgIChzZXQhIGdlb21ldHJ5IChtYWtlLWdlb21ldHJ5IGhlaWdodG1hcCkpXG4gICAgICAgICh1cGRhdGUtZ2VvbWV0cnkgZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcblxuICAgICAgKGwgXCJSZWJ1aWxkaW5nIHBsYW5lLi4uXCIpXG4gICAgICAodGltZVxuICAgICAgICAoc2NlbmUucmVtb3ZlIHBsYW5lKVxuICAgICAgICAoc2V0ISBwbGFuZSAobWFrZS1wbGFuZSBnZW9tZXRyeSkpXG4gICAgICAgIChzY2VuZS5hZGQgcGxhbmUpKSkpXG5cbiAgKGF0dGFjaC10by1kb20gcmVuZGVyZXIgZWxlbWVudC1pZCByZWZyZXNoKVxuICAoZGVmIGNvbnRyb2xzIChtYWtlLWNvbnRyb2xzIGNhbWVyYSByZW5kZXJlcikpXG5cbiAgKGRlZm4gcmVuZGVyIFtdXG4gICAgKGxldCBbZGVsdGEgKGNsb2NrLmdldERlbHRhKV1cbiAgICAgIChyZXF1ZXN0QW5pbWF0aW9uRnJhbWUgcmVuZGVyKVxuICAgICAgKC51cGRhdGUgY29udHJvbHMgZGVsdGEpXG4gICAgICAocmVuZGVyZXIucmVuZGVyIHNjZW5lIGNhbWVyYSkpKVxuXG4gIChyZWZyZXNoKVxuICAocmVuZGVyKVxuXG4gIG5pbClcblxuKGRlZm4gcnVuIFtdXG4gIChtYWtlLWZpbmFsIFwiZGVtby1maW5hbFwiKSlcblxuKCQgcnVuKVxuXG5cbjsgdmltOiBsdys9ZG8tdGltZXMgbHcrPWRvLW5lc3RlZCA6XG4iLCJcInVzZSBzdHJpY3RcIlxuXG5mdW5jdGlvbiBpb3RhKG4pIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlvdGEiLCIvKipcbiAqIERldGVybWluZSBpZiBhbiBvYmplY3QgaXMgQnVmZmVyXG4gKlxuICogQXV0aG9yOiAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBMaWNlbnNlOiAgTUlUXG4gKlxuICogYG5wbSBpbnN0YWxsIGlzLWJ1ZmZlcmBcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgcmV0dXJuICEhKG9iaiAhPSBudWxsICYmXG4gICAgKG9iai5faXNCdWZmZXIgfHwgLy8gRm9yIFNhZmFyaSA1LTcgKG1pc3NpbmcgT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3RvcilcbiAgICAgIChvYmouY29uc3RydWN0b3IgJiZcbiAgICAgIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiZcbiAgICAgIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlcihvYmopKVxuICAgICkpXG59XG4iLCJ2YXIgaW90YSA9IHJlcXVpcmUoXCJpb3RhLWFycmF5XCIpXG52YXIgaXNCdWZmZXIgPSByZXF1aXJlKFwiaXMtYnVmZmVyXCIpXG5cbnZhciBoYXNUeXBlZEFycmF5cyAgPSAoKHR5cGVvZiBGbG9hdDY0QXJyYXkpICE9PSBcInVuZGVmaW5lZFwiKVxuXG5mdW5jdGlvbiBjb21wYXJlMXN0KGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gLSBiWzBdXG59XG5cbmZ1bmN0aW9uIG9yZGVyKCkge1xuICB2YXIgc3RyaWRlID0gdGhpcy5zdHJpZGVcbiAgdmFyIHRlcm1zID0gbmV3IEFycmF5KHN0cmlkZS5sZW5ndGgpXG4gIHZhciBpXG4gIGZvcihpPTA7IGk8dGVybXMubGVuZ3RoOyArK2kpIHtcbiAgICB0ZXJtc1tpXSA9IFtNYXRoLmFicyhzdHJpZGVbaV0pLCBpXVxuICB9XG4gIHRlcm1zLnNvcnQoY29tcGFyZTFzdClcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSh0ZXJtcy5sZW5ndGgpXG4gIGZvcihpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gdGVybXNbaV1bMV1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVDb25zdHJ1Y3RvcihkdHlwZSwgZGltZW5zaW9uKSB7XG4gIHZhciBjbGFzc05hbWUgPSBbXCJWaWV3XCIsIGRpbWVuc2lvbiwgXCJkXCIsIGR0eXBlXS5qb2luKFwiXCIpXG4gIGlmKGRpbWVuc2lvbiA8IDApIHtcbiAgICBjbGFzc05hbWUgPSBcIlZpZXdfTmlsXCIgKyBkdHlwZVxuICB9XG4gIHZhciB1c2VHZXR0ZXJzID0gKGR0eXBlID09PSBcImdlbmVyaWNcIilcblxuICBpZihkaW1lbnNpb24gPT09IC0xKSB7XG4gICAgLy9TcGVjaWFsIGNhc2UgZm9yIHRyaXZpYWwgYXJyYXlzXG4gICAgdmFyIGNvZGUgPVxuICAgICAgXCJmdW5jdGlvbiBcIitjbGFzc05hbWUrXCIoYSl7dGhpcy5kYXRhPWE7fTtcXFxudmFyIHByb3RvPVwiK2NsYXNzTmFtZStcIi5wcm90b3R5cGU7XFxcbnByb3RvLmR0eXBlPSdcIitkdHlwZStcIic7XFxcbnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIC0xfTtcXFxucHJvdG8uc2l6ZT0wO1xcXG5wcm90by5kaW1lbnNpb249LTE7XFxcbnByb3RvLnNoYXBlPXByb3RvLnN0cmlkZT1wcm90by5vcmRlcj1bXTtcXFxucHJvdG8ubG89cHJvdG8uaGk9cHJvdG8udHJhbnNwb3NlPXByb3RvLnN0ZXA9XFxcbmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhKTt9O1xcXG5wcm90by5nZXQ9cHJvdG8uc2V0PWZ1bmN0aW9uKCl7fTtcXFxucHJvdG8ucGljaz1mdW5jdGlvbigpe3JldHVybiBudWxsfTtcXFxucmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF9cIitjbGFzc05hbWUrXCIoYSl7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIoYSk7fVwiXG4gICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbihjb2RlKVxuICAgIHJldHVybiBwcm9jZWR1cmUoKVxuICB9IGVsc2UgaWYoZGltZW5zaW9uID09PSAwKSB7XG4gICAgLy9TcGVjaWFsIGNhc2UgZm9yIDBkIGFycmF5c1xuICAgIHZhciBjb2RlID1cbiAgICAgIFwiZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiKGEsZCkge1xcXG50aGlzLmRhdGEgPSBhO1xcXG50aGlzLm9mZnNldCA9IGRcXFxufTtcXFxudmFyIHByb3RvPVwiK2NsYXNzTmFtZStcIi5wcm90b3R5cGU7XFxcbnByb3RvLmR0eXBlPSdcIitkdHlwZStcIic7XFxcbnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMub2Zmc2V0fTtcXFxucHJvdG8uZGltZW5zaW9uPTA7XFxcbnByb3RvLnNpemU9MTtcXFxucHJvdG8uc2hhcGU9XFxcbnByb3RvLnN0cmlkZT1cXFxucHJvdG8ub3JkZXI9W107XFxcbnByb3RvLmxvPVxcXG5wcm90by5oaT1cXFxucHJvdG8udHJhbnNwb3NlPVxcXG5wcm90by5zdGVwPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9jb3B5KCkge1xcXG5yZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsdGhpcy5vZmZzZXQpXFxcbn07XFxcbnByb3RvLnBpY2s9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3BpY2soKXtcXFxucmV0dXJuIFRyaXZpYWxBcnJheSh0aGlzLmRhdGEpO1xcXG59O1xcXG5wcm90by52YWx1ZU9mPXByb3RvLmdldD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfZ2V0KCl7XFxcbnJldHVybiBcIisodXNlR2V0dGVycyA/IFwidGhpcy5kYXRhLmdldCh0aGlzLm9mZnNldClcIiA6IFwidGhpcy5kYXRhW3RoaXMub2Zmc2V0XVwiKStcblwifTtcXFxucHJvdG8uc2V0PWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9zZXQodil7XFxcbnJldHVybiBcIisodXNlR2V0dGVycyA/IFwidGhpcy5kYXRhLnNldCh0aGlzLm9mZnNldCx2KVwiIDogXCJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdPXZcIikrXCJcXFxufTtcXFxucmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF9cIitjbGFzc05hbWUrXCIoYSxiLGMsZCl7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIoYSxkKX1cIlxuICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oXCJUcml2aWFsQXJyYXlcIiwgY29kZSlcbiAgICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdWzBdKVxuICB9XG5cbiAgdmFyIGNvZGUgPSBbXCIndXNlIHN0cmljdCdcIl1cblxuICAvL0NyZWF0ZSBjb25zdHJ1Y3RvciBmb3Igdmlld1xuICB2YXIgaW5kaWNlcyA9IGlvdGEoZGltZW5zaW9uKVxuICB2YXIgYXJncyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFwiaVwiK2kgfSlcbiAgdmFyIGluZGV4X3N0ciA9IFwidGhpcy5vZmZzZXQrXCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICAgIHJldHVybiBcInRoaXMuc3RyaWRlW1wiICsgaSArIFwiXSppXCIgKyBpXG4gICAgICB9KS5qb2luKFwiK1wiKVxuICB2YXIgc2hhcGVBcmcgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJiXCIraVxuICAgIH0pLmpvaW4oXCIsXCIpXG4gIHZhciBzdHJpZGVBcmcgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJjXCIraVxuICAgIH0pLmpvaW4oXCIsXCIpXG4gIGNvZGUucHVzaChcbiAgICBcImZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIihhLFwiICsgc2hhcGVBcmcgKyBcIixcIiArIHN0cmlkZUFyZyArIFwiLGQpe3RoaXMuZGF0YT1hXCIsXG4gICAgICBcInRoaXMuc2hhcGU9W1wiICsgc2hhcGVBcmcgKyBcIl1cIixcbiAgICAgIFwidGhpcy5zdHJpZGU9W1wiICsgc3RyaWRlQXJnICsgXCJdXCIsXG4gICAgICBcInRoaXMub2Zmc2V0PWR8MH1cIixcbiAgICBcInZhciBwcm90bz1cIitjbGFzc05hbWUrXCIucHJvdG90eXBlXCIsXG4gICAgXCJwcm90by5kdHlwZT0nXCIrZHR5cGUrXCInXCIsXG4gICAgXCJwcm90by5kaW1lbnNpb249XCIrZGltZW5zaW9uKVxuXG4gIC8vdmlldy5zaXplOlxuICBjb2RlLnB1c2goXCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ3NpemUnLHtnZXQ6ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3NpemUoKXtcXFxucmV0dXJuIFwiK2luZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFwidGhpcy5zaGFwZVtcIitpK1wiXVwiIH0pLmpvaW4oXCIqXCIpLFxuXCJ9fSlcIilcblxuICAvL3ZpZXcub3JkZXI6XG4gIGlmKGRpbWVuc2lvbiA9PT0gMSkge1xuICAgIGNvZGUucHVzaChcInByb3RvLm9yZGVyPVswXVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcIk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywnb3JkZXInLHtnZXQ6XCIpXG4gICAgaWYoZGltZW5zaW9uIDwgNCkge1xuICAgICAgY29kZS5wdXNoKFwiZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX29yZGVyKCl7XCIpXG4gICAgICBpZihkaW1lbnNpb24gPT09IDIpIHtcbiAgICAgICAgY29kZS5wdXNoKFwicmV0dXJuIChNYXRoLmFicyh0aGlzLnN0cmlkZVswXSk+TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pKT9bMSwwXTpbMCwxXX19KVwiKVxuICAgICAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMykge1xuICAgICAgICBjb2RlLnB1c2goXG5cInZhciBzMD1NYXRoLmFicyh0aGlzLnN0cmlkZVswXSksczE9TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pLHMyPU1hdGguYWJzKHRoaXMuc3RyaWRlWzJdKTtcXFxuaWYoczA+czEpe1xcXG5pZihzMT5zMil7XFxcbnJldHVybiBbMiwxLDBdO1xcXG59ZWxzZSBpZihzMD5zMil7XFxcbnJldHVybiBbMSwyLDBdO1xcXG59ZWxzZXtcXFxucmV0dXJuIFsxLDAsMl07XFxcbn1cXFxufWVsc2UgaWYoczA+czIpe1xcXG5yZXR1cm4gWzIsMCwxXTtcXFxufWVsc2UgaWYoczI+czEpe1xcXG5yZXR1cm4gWzAsMSwyXTtcXFxufWVsc2V7XFxcbnJldHVybiBbMCwyLDFdO1xcXG59fX0pXCIpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChcIk9SREVSfSlcIilcbiAgICB9XG4gIH1cblxuICAvL3ZpZXcuc2V0KGkwLCAuLi4sIHYpOlxuICBjb2RlLnB1c2goXG5cInByb3RvLnNldD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfc2V0KFwiK2FyZ3Muam9pbihcIixcIikrXCIsdil7XCIpXG4gIGlmKHVzZUdldHRlcnMpIHtcbiAgICBjb2RlLnB1c2goXCJyZXR1cm4gdGhpcy5kYXRhLnNldChcIitpbmRleF9zdHIrXCIsdil9XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIHRoaXMuZGF0YVtcIitpbmRleF9zdHIrXCJdPXZ9XCIpXG4gIH1cblxuICAvL3ZpZXcuZ2V0KGkwLCAuLi4pOlxuICBjb2RlLnB1c2goXCJwcm90by5nZXQ9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2dldChcIithcmdzLmpvaW4oXCIsXCIpK1wiKXtcIilcbiAgaWYodXNlR2V0dGVycykge1xuICAgIGNvZGUucHVzaChcInJldHVybiB0aGlzLmRhdGEuZ2V0KFwiK2luZGV4X3N0citcIil9XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIHRoaXMuZGF0YVtcIitpbmRleF9zdHIrXCJdfVwiKVxuICB9XG5cbiAgLy92aWV3LmluZGV4OlxuICBjb2RlLnB1c2goXG4gICAgXCJwcm90by5pbmRleD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfaW5kZXgoXCIsIGFyZ3Muam9pbigpLCBcIil7cmV0dXJuIFwiK2luZGV4X3N0citcIn1cIilcblxuICAvL3ZpZXcuaGkoKTpcbiAgY29kZS5wdXNoKFwicHJvdG8uaGk9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2hpKFwiK2FyZ3Muam9pbihcIixcIikrXCIpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKHRoaXMuZGF0YSxcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gW1wiKHR5cGVvZiBpXCIsaSxcIiE9PSdudW1iZXInfHxpXCIsaSxcIjwwKT90aGlzLnNoYXBlW1wiLCBpLCBcIl06aVwiLCBpLFwifDBcIl0uam9pbihcIlwiKVxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcInRoaXMuc3RyaWRlW1wiK2kgKyBcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLHRoaXMub2Zmc2V0KX1cIilcblxuICAvL3ZpZXcubG8oKTpcbiAgdmFyIGFfdmFycyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFwiYVwiK2krXCI9dGhpcy5zaGFwZVtcIitpK1wiXVwiIH0pXG4gIHZhciBjX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcImNcIitpK1wiPXRoaXMuc3RyaWRlW1wiK2krXCJdXCIgfSlcbiAgY29kZS5wdXNoKFwicHJvdG8ubG89ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2xvKFwiK2FyZ3Muam9pbihcIixcIikrXCIpe3ZhciBiPXRoaXMub2Zmc2V0LGQ9MCxcIithX3ZhcnMuam9pbihcIixcIikrXCIsXCIrY192YXJzLmpvaW4oXCIsXCIpKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcblwiaWYodHlwZW9mIGlcIitpK1wiPT09J251bWJlcicmJmlcIitpK1wiPj0wKXtcXFxuZD1pXCIraStcInwwO1xcXG5iKz1jXCIraStcIipkO1xcXG5hXCIraStcIi09ZH1cIilcbiAgfVxuICBjb2RlLnB1c2goXCJyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiYVwiK2lcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJjXCIraVxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLGIpfVwiKVxuXG4gIC8vdmlldy5zdGVwKCk6XG4gIGNvZGUucHVzaChcInByb3RvLnN0ZXA9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3N0ZXAoXCIrYXJncy5qb2luKFwiLFwiKStcIil7dmFyIFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImFcIitpK1wiPXRoaXMuc2hhcGVbXCIraStcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImJcIitpK1wiPXRoaXMuc3RyaWRlW1wiK2krXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIixjPXRoaXMub2Zmc2V0LGQ9MCxjZWlsPU1hdGguY2VpbFwiKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcblwiaWYodHlwZW9mIGlcIitpK1wiPT09J251bWJlcicpe1xcXG5kPWlcIitpK1wifDA7XFxcbmlmKGQ8MCl7XFxcbmMrPWJcIitpK1wiKihhXCIraStcIi0xKTtcXFxuYVwiK2krXCI9Y2VpbCgtYVwiK2krXCIvZClcXFxufWVsc2V7XFxcbmFcIitpK1wiPWNlaWwoYVwiK2krXCIvZClcXFxufVxcXG5iXCIraStcIio9ZFxcXG59XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwicmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImFcIiArIGlcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJiXCIgKyBpXG4gICAgfSkuam9pbihcIixcIikrXCIsYyl9XCIpXG5cbiAgLy92aWV3LnRyYW5zcG9zZSgpOlxuICB2YXIgdFNoYXBlID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgdmFyIHRTdHJpZGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIHRTaGFwZVtpXSA9IFwiYVtpXCIraStcIl1cIlxuICAgIHRTdHJpZGVbaV0gPSBcImJbaVwiK2krXCJdXCJcbiAgfVxuICBjb2RlLnB1c2goXCJwcm90by50cmFuc3Bvc2U9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3RyYW5zcG9zZShcIithcmdzK1wiKXtcIitcbiAgICBhcmdzLm1hcChmdW5jdGlvbihuLGlkeCkgeyByZXR1cm4gbiArIFwiPShcIiArIG4gKyBcIj09PXVuZGVmaW5lZD9cIiArIGlkeCArIFwiOlwiICsgbiArIFwifDApXCJ9KS5qb2luKFwiO1wiKSxcbiAgICBcInZhciBhPXRoaXMuc2hhcGUsYj10aGlzLnN0cmlkZTtyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsXCIrdFNoYXBlLmpvaW4oXCIsXCIpK1wiLFwiK3RTdHJpZGUuam9pbihcIixcIikrXCIsdGhpcy5vZmZzZXQpfVwiKVxuXG4gIC8vdmlldy5waWNrKCk6XG4gIGNvZGUucHVzaChcInByb3RvLnBpY2s9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3BpY2soXCIrYXJncytcIil7dmFyIGE9W10sYj1bXSxjPXRoaXMub2Zmc2V0XCIpXG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgY29kZS5wdXNoKFwiaWYodHlwZW9mIGlcIitpK1wiPT09J251bWJlcicmJmlcIitpK1wiPj0wKXtjPShjK3RoaXMuc3RyaWRlW1wiK2krXCJdKmlcIitpK1wiKXwwfWVsc2V7YS5wdXNoKHRoaXMuc2hhcGVbXCIraStcIl0pO2IucHVzaCh0aGlzLnN0cmlkZVtcIitpK1wiXSl9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwidmFyIGN0b3I9Q1RPUl9MSVNUW2EubGVuZ3RoKzFdO3JldHVybiBjdG9yKHRoaXMuZGF0YSxhLGIsYyl9XCIpXG5cbiAgLy9BZGQgcmV0dXJuIHN0YXRlbWVudFxuICBjb2RlLnB1c2goXCJyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0X1wiK2NsYXNzTmFtZStcIihkYXRhLHNoYXBlLHN0cmlkZSxvZmZzZXQpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKGRhdGEsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwic2hhcGVbXCIraStcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcInN0cmlkZVtcIitpK1wiXVwiXG4gICAgfSkuam9pbihcIixcIikrXCIsb2Zmc2V0KX1cIilcblxuICAvL0NvbXBpbGUgcHJvY2VkdXJlXG4gIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oXCJDVE9SX0xJU1RcIiwgXCJPUkRFUlwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV0sIG9yZGVyKVxufVxuXG5mdW5jdGlvbiBhcnJheURUeXBlKGRhdGEpIHtcbiAgaWYoaXNCdWZmZXIoZGF0YSkpIHtcbiAgICByZXR1cm4gXCJidWZmZXJcIlxuICB9XG4gIGlmKGhhc1R5cGVkQXJyYXlzKSB7XG4gICAgc3dpdGNoKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSkge1xuICAgICAgY2FzZSBcIltvYmplY3QgRmxvYXQ2NEFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJmbG9hdDY0XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEZsb2F0MzJBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiZmxvYXQzMlwiXG4gICAgICBjYXNlIFwiW29iamVjdCBJbnQ4QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImludDhcIlxuICAgICAgY2FzZSBcIltvYmplY3QgSW50MTZBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiaW50MTZcIlxuICAgICAgY2FzZSBcIltvYmplY3QgSW50MzJBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiaW50MzJcIlxuICAgICAgY2FzZSBcIltvYmplY3QgVWludDhBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwidWludDhcIlxuICAgICAgY2FzZSBcIltvYmplY3QgVWludDE2QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcInVpbnQxNlwiXG4gICAgICBjYXNlIFwiW29iamVjdCBVaW50MzJBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwidWludDMyXCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJ1aW50OF9jbGFtcGVkXCJcbiAgICB9XG4gIH1cbiAgaWYoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgIHJldHVybiBcImFycmF5XCJcbiAgfVxuICByZXR1cm4gXCJnZW5lcmljXCJcbn1cblxudmFyIENBQ0hFRF9DT05TVFJVQ1RPUlMgPSB7XG4gIFwiZmxvYXQzMlwiOltdLFxuICBcImZsb2F0NjRcIjpbXSxcbiAgXCJpbnQ4XCI6W10sXG4gIFwiaW50MTZcIjpbXSxcbiAgXCJpbnQzMlwiOltdLFxuICBcInVpbnQ4XCI6W10sXG4gIFwidWludDE2XCI6W10sXG4gIFwidWludDMyXCI6W10sXG4gIFwiYXJyYXlcIjpbXSxcbiAgXCJ1aW50OF9jbGFtcGVkXCI6W10sXG4gIFwiYnVmZmVyXCI6W10sXG4gIFwiZ2VuZXJpY1wiOltdXG59XG5cbjsoZnVuY3Rpb24oKSB7XG4gIGZvcih2YXIgaWQgaW4gQ0FDSEVEX0NPTlNUUlVDVE9SUykge1xuICAgIENBQ0hFRF9DT05TVFJVQ1RPUlNbaWRdLnB1c2goY29tcGlsZUNvbnN0cnVjdG9yKGlkLCAtMSkpXG4gIH1cbn0pO1xuXG5mdW5jdGlvbiB3cmFwcGVkTkRBcnJheUN0b3IoZGF0YSwgc2hhcGUsIHN0cmlkZSwgb2Zmc2V0KSB7XG4gIGlmKGRhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBjdG9yID0gQ0FDSEVEX0NPTlNUUlVDVE9SUy5hcnJheVswXVxuICAgIHJldHVybiBjdG9yKFtdKVxuICB9IGVsc2UgaWYodHlwZW9mIGRhdGEgPT09IFwibnVtYmVyXCIpIHtcbiAgICBkYXRhID0gW2RhdGFdXG4gIH1cbiAgaWYoc2hhcGUgPT09IHVuZGVmaW5lZCkge1xuICAgIHNoYXBlID0gWyBkYXRhLmxlbmd0aCBdXG4gIH1cbiAgdmFyIGQgPSBzaGFwZS5sZW5ndGhcbiAgaWYoc3RyaWRlID09PSB1bmRlZmluZWQpIHtcbiAgICBzdHJpZGUgPSBuZXcgQXJyYXkoZClcbiAgICBmb3IodmFyIGk9ZC0xLCBzej0xOyBpPj0wOyAtLWkpIHtcbiAgICAgIHN0cmlkZVtpXSA9IHN6XG4gICAgICBzeiAqPSBzaGFwZVtpXVxuICAgIH1cbiAgfVxuICBpZihvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIG9mZnNldCA9IDBcbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgIGlmKHN0cmlkZVtpXSA8IDApIHtcbiAgICAgICAgb2Zmc2V0IC09IChzaGFwZVtpXS0xKSpzdHJpZGVbaV1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIGR0eXBlID0gYXJyYXlEVHlwZShkYXRhKVxuICB2YXIgY3Rvcl9saXN0ID0gQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV1cbiAgd2hpbGUoY3Rvcl9saXN0Lmxlbmd0aCA8PSBkKzEpIHtcbiAgICBjdG9yX2xpc3QucHVzaChjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGN0b3JfbGlzdC5sZW5ndGgtMSkpXG4gIH1cbiAgdmFyIGN0b3IgPSBjdG9yX2xpc3RbZCsxXVxuICByZXR1cm4gY3RvcihkYXRhLCBzaGFwZSwgc3RyaWRlLCBvZmZzZXQpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gd3JhcHBlZE5EQXJyYXlDdG9yXG4iXX0=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/terrain3.js	Sat Jun 25 15:57:05 2016 +0000
@@ -0,0 +1,951 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+{
+    var _ns_ = {
+        id: 'demo',
+        doc: void 0
+    };
+    var ndarray = require('ndarray');
+}
+var width = exports.width = 610;
+var height = exports.height = 400;
+var wireframe = exports.wireframe = true;
+var wireframeWidth = exports.wireframeWidth = 1.2;
+var terrainHeight = exports.terrainHeight = 50;
+var terrainSize = exports.terrainSize = 100;
+void 0;
+void 0;
+void 0;
+var inc = exports.inc = function inc(x) {
+    return x + 1;
+};
+var dec = exports.dec = function dec(x) {
+    return x - 1;
+};
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+var midpoint = exports.midpoint = function midpoint(a, b) {
+    return (a + b) / 2;
+};
+var average2 = exports.average2 = function average2(a, b) {
+    return (a + b) / 2;
+};
+var average4 = exports.average4 = function average4(a, b, c, d) {
+    return (a + b + c + d) / 4;
+};
+var safeAverage = exports.safeAverage = function safeAverage(a, b, c, d) {
+    return function () {
+        var totalø1 = 0;
+        var countø1 = 0;
+        a ? (function () {
+            totalø1 = totalø1 + a;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        b ? (function () {
+            totalø1 = totalø1 + b;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        c ? (function () {
+            totalø1 = totalø1 + c;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        d ? (function () {
+            totalø1 = totalø1 + d;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        return totalø1 / countø1;
+    }.call(this);
+};
+var isEven = exports.isEven = function isEven(n) {
+    return 0 == n % 2;
+};
+var isOdd = exports.isOdd = function isOdd(n) {
+    return 1 == n % 2;
+};
+var rand = exports.rand = function rand() {
+    return Math.random();
+};
+var randAroundZero = exports.randAroundZero = function randAroundZero(spread) {
+    return spread * rand() * 2 - spread;
+};
+var jitter = exports.jitter = function jitter(value, spread) {
+    return value + randAroundZero(spread);
+};
+var heightmapResolution = exports.heightmapResolution = function heightmapResolution(heightmap) {
+    return heightmap.shape[0];
+};
+var heightmapLastIndex = exports.heightmapLastIndex = function heightmapLastIndex(heightmap) {
+    return dec(heightmapResolution(heightmap));
+};
+var heightmapCenterIndex = exports.heightmapCenterIndex = function heightmapCenterIndex(heightmap) {
+    return midpoint(0, heightmapLastIndex(heightmap));
+};
+var heightmapGet = exports.heightmapGet = function heightmapGet(heightmap, x, y) {
+    return heightmap.get(x, y);
+};
+var heightmapGetSafe = exports.heightmapGetSafe = function heightmapGetSafe(heightmap, x, y) {
+    return function () {
+        var lastø1 = heightmapLastIndex(heightmap);
+        return 0 <= x && x <= lastø1 && (0 <= y && y <= lastø1) ? (function () {
+            return heightmapGet(heightmap, x, y);
+        })() : void 0;
+    }.call(this);
+};
+var heightmapSet = exports.heightmapSet = function heightmapSet(heightmap, x, y, val) {
+    return heightmap.set(x, y, val);
+};
+var heightmapSetIfUnset = exports.heightmapSetIfUnset = function heightmapSetIfUnset(heightmap, x, y, val) {
+    return 0 == heightmapGet(heightmap, x, y) ? (function () {
+        return heightmapSet(heightmap, x, y, val);
+    })() : void 0;
+};
+var normalize = exports.normalize = function normalize(heightmap) {
+    return function () {
+        var maxø1 = 0 - Infinity;
+        var minø1 = Infinity;
+        (function () {
+            var array2ø1 = heightmap;
+            return function () {
+                var G__3ø1 = array2ø1.data.length;
+                return function loop() {
+                    var recur = loop;
+                    var index1ø1 = 0;
+                    do {
+                        recur = index1ø1 < G__3ø1 ? (function () {
+                            (function () {
+                                var elø1 = array2ø1.data[index1ø1];
+                                maxø1 < elø1 ? (function () {
+                                    return maxø1 = elø1;
+                                })() : void 0;
+                                return minø1 > elø1 ? (function () {
+                                    return minø1 = elø1;
+                                })() : void 0;
+                            }.call(this));
+                            return loop[0] = inc(index1ø1), loop;
+                        })() : void 0;
+                    } while (index1ø1 = loop[0], recur === loop);
+                    return recur;
+                }.call(this);
+            }.call(this);
+        }.call(this));
+        return function () {
+            var spanø1 = maxø1 - minø1;
+            return function () {
+                var array4ø1 = heightmap;
+                return function () {
+                    var G__5ø1 = array4ø1.shape[0];
+                    return function loop() {
+                        var recur = loop;
+                        var xø1 = 0;
+                        do {
+                            recur = xø1 < G__5ø1 ? (function () {
+                                (function () {
+                                    var G__6ø1 = array4ø1.shape[1];
+                                    return function loop() {
+                                        var recur = loop;
+                                        var yø1 = 0;
+                                        do {
+                                            recur = yø1 < G__6ø1 ? (function () {
+                                                (function () {
+                                                    return heightmapSet(heightmap, xø1, yø1, (heightmapGet(heightmap, xø1, yø1) - minø1) / spanø1);
+                                                })();
+                                                return loop[0] = inc(yø1), loop;
+                                            })() : void 0;
+                                        } while (yø1 = loop[0], recur === loop);
+                                        return recur;
+                                    }.call(this);
+                                }.call(this));
+                                return loop[0] = inc(xø1), loop;
+                            })() : void 0;
+                        } while (xø1 = loop[0], recur === loop);
+                        return recur;
+                    }.call(this);
+                }.call(this);
+            }.call(this);
+        }.call(this);
+    }.call(this);
+};
+var makeHeightmap = exports.makeHeightmap = function makeHeightmap(exponent) {
+    return function () {
+        var resolutionø1 = Math.pow(2, exponent) + 1;
+        return function () {
+            var heightmapø1 = ndarray(new Float64Array(resolutionø1 * resolutionø1), [
+                resolutionø1,
+                resolutionø1
+            ]);
+            heightmapø1.exponent = exponent;
+            heightmapø1.resolution = resolutionø1;
+            heightmapø1.last = dec(resolutionø1);
+            return heightmapø1;
+        }.call(this);
+    }.call(this);
+};
+var topLeftCorner = exports.topLeftCorner = function topLeftCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(0, 0).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var topRightCorner = exports.topRightCorner = function topRightCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(centerø1, 0).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var bottomLeftCorner = exports.bottomLeftCorner = function bottomLeftCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(0, centerø1).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var bottomRightCorner = exports.bottomRightCorner = function bottomRightCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(centerø1, centerø1).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var dsInitCorners = exports.dsInitCorners = function dsInitCorners(heightmap) {
+    return function () {
+        var lastø1 = heightmapLastIndex(heightmap);
+        heightmapSet(heightmap, 0, 0, rand());
+        heightmapSet(heightmap, 0, lastø1, rand());
+        heightmapSet(heightmap, lastø1, 0, rand());
+        return heightmapSet(heightmap, lastø1, lastø1, rand());
+    }.call(this);
+};
+var dsSquare = exports.dsSquare = function dsSquare(heightmap, x, y, radius, spread) {
+    return function () {
+        var newHeightø1 = jitter(average4(heightmapGet(heightmap, x - radius, y - radius), heightmapGet(heightmap, x - radius, y + radius), heightmapGet(heightmap, x + radius, y - radius), heightmapGet(heightmap, x + radius, y + radius)), spread);
+        return heightmapSet(heightmap, x, y, newHeightø1);
+    }.call(this);
+};
+var dsDiamond = exports.dsDiamond = function dsDiamond(heightmap, x, y, radius, spread) {
+    return function () {
+        var newHeightø1 = jitter(safeAverage(heightmapGetSafe(heightmap, x - radius, y), heightmapGetSafe(heightmap, x + radius, y), heightmapGetSafe(heightmap, x, y - radius), heightmapGetSafe(heightmap, x, y + radius)), spread);
+        return heightmapSet(heightmap, x, y, newHeightø1);
+    }.call(this);
+};
+var dsSquares = exports.dsSquares = function dsSquares(heightmap, radius, spread) {
+    return function () {
+        var start8ø1 = radius;
+        var end9ø1 = heightmapResolution(heightmap);
+        var stride7ø1 = 2 * radius;
+        return function loop() {
+            var recur = loop;
+            var xø1 = start8ø1;
+            do {
+                recur = xø1 < end9ø1 ? (function () {
+                    (function loop() {
+                        var recur = loop;
+                        var yø1 = start8ø1;
+                        do {
+                            recur = yø1 < end9ø1 ? (function () {
+                                (function () {
+                                    return dsSquare(heightmap, xø1, yø1, radius, spread);
+                                })();
+                                return loop[0] = yø1 + stride7ø1, loop;
+                            })() : void 0;
+                        } while (yø1 = loop[0], recur === loop);
+                        return recur;
+                    }.call(this));
+                    return loop[0] = xø1 + stride7ø1, loop;
+                })() : void 0;
+            } while (xø1 = loop[0], recur === loop);
+            return recur;
+        }.call(this);
+    }.call(this);
+};
+var dsDiamonds = exports.dsDiamonds = function dsDiamonds(heightmap, radius, spread) {
+    return function () {
+        var sizeø1 = heightmapResolution(heightmap);
+        return function () {
+            var start11ø1 = 0;
+            var end12ø1 = sizeø1;
+            var stride10ø1 = radius;
+            return function loop() {
+                var recur = loop;
+                var yø1 = start11ø1;
+                do {
+                    recur = yø1 < end12ø1 ? (function () {
+                        (function () {
+                            return function () {
+                                var shiftø1 = isEven(yø1 / radius) ? radius : 0;
+                                return function () {
+                                    var start14ø1 = shiftø1;
+                                    var end15ø1 = sizeø1;
+                                    var stride13ø1 = 2 * radius;
+                                    return function loop() {
+                                        var recur = loop;
+                                        var xø1 = start14ø1;
+                                        do {
+                                            recur = xø1 < end15ø1 ? (function () {
+                                                (function () {
+                                                    return dsDiamond(heightmap, xø1, yø1, radius, spread);
+                                                })();
+                                                return loop[0] = xø1 + stride13ø1, loop;
+                                            })() : void 0;
+                                        } while (xø1 = loop[0], recur === loop);
+                                        return recur;
+                                    }.call(this);
+                                }.call(this);
+                            }.call(this);
+                        })();
+                        return loop[0] = yø1 + stride10ø1, loop;
+                    })() : void 0;
+                } while (yø1 = loop[0], recur === loop);
+                return recur;
+            }.call(this);
+        }.call(this);
+    }.call(this);
+};
+var diamondSquare = exports.diamondSquare = function diamondSquare(heightmap) {
+    return function () {
+        var initialSpreadø1 = 0.3;
+        var spreadReductionø1 = 0.5;
+        var centerø1 = heightmapCenterIndex(heightmap);
+        var sizeø1 = heightmap.shape[0];
+        dsInitCorners(heightmap);
+        (function loop() {
+            var recur = loop;
+            var radiusø1 = centerø1;
+            var spreadø1 = initialSpreadø1;
+            do {
+                recur = radiusø1 >= 1 ? (function () {
+                    dsSquares(heightmap, radiusø1, spreadø1);
+                    dsDiamonds(heightmap, radiusø1, spreadø1);
+                    return loop[0] = radiusø1 / 2, loop[1] = spreadø1 * spreadReductionø1, loop;
+                })() : void 0;
+            } while (radiusø1 = loop[0], spreadø1 = loop[1], recur === loop);
+            return recur;
+        }.call(this));
+        return normalize(heightmap);
+    }.call(this);
+};
+var diamondSquare1 = exports.diamondSquare1 = function diamondSquare1(heightmap) {
+    dsInitCorners(heightmap);
+    return normalize(heightmap);
+};
+var diamondSquare2 = exports.diamondSquare2 = function diamondSquare2(heightmap) {
+    return function () {
+        var initialSpreadø1 = 0.3;
+        var spreadReductionø1 = 0.5;
+        var centerø1 = heightmapCenterIndex(heightmap);
+        var sizeø1 = heightmap.shape[0];
+        dsInitCorners(heightmap);
+        dsSquares(heightmap, centerø1, initialSpreadø1);
+        return normalize(heightmap);
+    }.call(this);
+};
+var diamondSquare3 = exports.diamondSquare3 = function diamondSquare3(heightmap) {
+    return function () {
+        var initialSpreadø1 = 0.3;
+        var spreadReductionø1 = 0.5;
+        var centerø1 = heightmapCenterIndex(heightmap);
+        var sizeø1 = heightmap.shape[0];
+        dsInitCorners(heightmap);
+        dsSquares(heightmap, centerø1, initialSpreadø1);
+        dsDiamonds(heightmap, centerø1, initialSpreadø1);
+        dsSquares(heightmap, centerø1 / 2, spreadReductionø1 * initialSpreadø1);
+        dsDiamonds(heightmap, centerø1 / 2, spreadReductionø1 * initialSpreadø1);
+        return normalize(heightmap);
+    }.call(this);
+};
+var makeDirectionalLight = exports.makeDirectionalLight = function makeDirectionalLight() {
+    return function () {
+        var lightø1 = new THREE.DirectionalLight(16777215, 1);
+        lightø1.position.set(100, 0, 150);
+        return lightø1;
+    }.call(this);
+};
+var makeCamera = exports.makeCamera = function makeCamera() {
+    return function () {
+        var cameraø1 = new THREE.PerspectiveCamera(55, width / height, 0.1, 1000);
+        cameraø1.position.set(0, -100, 150);
+        return cameraø1;
+    }.call(this);
+};
+var makeRenderer = exports.makeRenderer = function makeRenderer() {
+    return function () {
+        var rendererø1 = new THREE.WebGLRenderer({ 'antialias': false });
+        rendererø1.setClearColor(16777215);
+        rendererø1.setSize(width, height);
+        rendererø1.setPixelRatio(2);
+        return rendererø1;
+    }.call(this);
+};
+var makeGeometry = exports.makeGeometry = function makeGeometry(heightmap) {
+    return function () {
+        var resolutionø1 = heightmap.shape[0];
+        var geometryø1 = new THREE.PlaneGeometry(terrainSize, terrainSize, resolutionø1 - 1, resolutionø1 - 1);
+        return geometryø1;
+    }.call(this);
+};
+var makeControls = exports.makeControls = function makeControls(camera, renderer) {
+    return function () {
+        var controlsø1 = new THREE.TrackballControls(camera, renderer.domElement);
+        controlsø1.rotateSpeed = 1.4;
+        controlsø1.zoomSpeed = 0.5;
+        controlsø1.staticMoving = true;
+        controlsø1.dynamicDampingFactor = 0.3;
+        return controlsø1;
+    }.call(this);
+};
+var makePlane = exports.makePlane = function makePlane(geometry) {
+    return function () {
+        var materialø1 = new THREE.MeshLambertMaterial({
+            'wireframe': wireframe,
+            'wireframeLinewidth': wireframeWidth,
+            'color': 47872
+        });
+        return new THREE.Mesh(geometry, materialø1);
+    }.call(this);
+};
+var attachToDom = exports.attachToDom = function attachToDom(renderer, elName, refreshFn) {
+    return function () {
+        var containerø1 = document.getElementById(elName);
+        var settingsø1 = document.createElement('div');
+        var refreshButtonø1 = document.createElement('button');
+        var buttonTextø1 = document.createTextNode('Refresh');
+        var cancelScrollø1 = function (e) {
+            return e.preventDefault();
+        };
+        refreshButtonø1.onclick = refreshFn;
+        renderer.domElement.onmousewheel = cancelScrollø1;
+        renderer.domElement.addEventListener('MozMousePixelScroll', cancelScrollø1, false);
+        refreshButtonø1.appendChild(buttonTextø1);
+        containerø1.appendChild(renderer.domElement);
+        containerø1.appendChild(settingsø1);
+        return settingsø1.appendChild(refreshButtonø1);
+    }.call(this);
+};
+var updateGeometry = exports.updateGeometry = function updateGeometry(geometry, heightmap) {
+    (function loop() {
+        var recur = loop;
+        var iø1 = 0;
+        do {
+            recur = iø1 < geometry.vertices.length ? (function () {
+                geometry.vertices[iø1].z = terrainHeight * heightmap.data[iø1];
+                return loop[0] = iø1 + 1, loop;
+            })() : void 0;
+        } while (iø1 = loop[0], recur === loop);
+        return recur;
+    }.call(this));
+    geometry.computeVertexNormals();
+    return geometry;
+};
+var makeDemo = exports.makeDemo = function makeDemo(elementId, algorithm, size) {
+    var scene = new THREE.Scene();
+    scene.add(new THREE.AxisHelper(100));
+    var clock = new THREE.Clock();
+    var camera = makeCamera();
+    var renderer = makeRenderer();
+    var geometry = void 0;
+    var plane = void 0;
+    scene.add(makeDirectionalLight());
+    scene.add(new THREE.AmbientLight(16777215, 0.05));
+    var refresh = function refresh() {
+        return function () {
+            var heightmapø1 = makeHeightmap(size);
+            console.log('Generating terrain...');
+            (function () {
+                var G__16ø1 = new Date().getTime();
+                var G__18ø1 = (function () {
+                    return algorithm(heightmapø1);
+                })();
+                var G__17ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__17ø1 - G__16ø1) + 'ms.');
+                return G__18ø1;
+            }.call(this));
+            console.log('Rebuilding geometry...');
+            (function () {
+                var G__19ø1 = new Date().getTime();
+                var G__21ø1 = (function () {
+                    geometry = makeGeometry(heightmapø1);
+                    return updateGeometry(geometry, heightmapø1);
+                })();
+                var G__20ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__20ø1 - G__19ø1) + 'ms.');
+                return G__21ø1;
+            }.call(this));
+            console.log('Rebuilding plane...');
+            return function () {
+                var G__22ø1 = new Date().getTime();
+                var G__24ø1 = (function () {
+                    scene.remove(plane);
+                    plane = makePlane(geometry);
+                    return scene.add(plane);
+                })();
+                var G__23ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__23ø1 - G__22ø1) + 'ms.');
+                return G__24ø1;
+            }.call(this);
+        }.call(this);
+    };
+    attachToDom(renderer, elementId, refresh);
+    var controls = makeControls(camera, renderer);
+    var render = function render() {
+        return function () {
+            var deltaø1 = clock.getDelta();
+            requestAnimationFrame(render);
+            controls.update(deltaø1);
+            return renderer.render(scene, camera);
+        }.call(this);
+    };
+    refresh();
+    render();
+    return void 0;
+};
+var makeFinal = exports.makeFinal = function makeFinal(elementId) {
+    var scene = new THREE.Scene();
+    scene.add(new THREE.AxisHelper(100));
+    var clock = new THREE.Clock();
+    var camera = makeCamera();
+    var renderer = makeRenderer();
+    var geometry = void 0;
+    var plane = void 0;
+    scene.add(makeDirectionalLight());
+    scene.add(new THREE.AmbientLight(16777215, 0.05));
+    var refresh = function refresh() {
+        return function () {
+            var heightmapø1 = makeHeightmap(6);
+            console.log('Generating terrain...');
+            (function () {
+                var G__25ø1 = new Date().getTime();
+                var G__27ø1 = (function () {
+                    return diamondSquare(heightmapø1);
+                })();
+                var G__26ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__26ø1 - G__25ø1) + 'ms.');
+                return G__27ø1;
+            }.call(this));
+            console.log('Rebuilding geometry...');
+            (function () {
+                var G__28ø1 = new Date().getTime();
+                var G__30ø1 = (function () {
+                    geometry = makeGeometry(heightmapø1);
+                    return updateGeometry(geometry, heightmapø1);
+                })();
+                var G__29ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__29ø1 - G__28ø1) + 'ms.');
+                return G__30ø1;
+            }.call(this));
+            console.log('Rebuilding plane...');
+            return function () {
+                var G__31ø1 = new Date().getTime();
+                var G__33ø1 = (function () {
+                    scene.remove(plane);
+                    plane = makePlane(geometry);
+                    return scene.add(plane);
+                })();
+                var G__32ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__32ø1 - G__31ø1) + 'ms.');
+                return G__33ø1;
+            }.call(this);
+        }.call(this);
+    };
+    attachToDom(renderer, elementId, refresh);
+    var controls = makeControls(camera, renderer);
+    var render = function render() {
+        return function () {
+            var deltaø1 = clock.getDelta();
+            requestAnimationFrame(render);
+            controls.update(deltaø1);
+            return renderer.render(scene, camera);
+        }.call(this);
+    };
+    refresh();
+    render();
+    return void 0;
+};
+var run = exports.run = function run() {
+    makeDemo('demo-1', diamondSquare1, 2);
+    makeDemo('demo-2', diamondSquare2, 4);
+    makeDemo('demo-3', diamondSquare3, 4);
+    return makeFinal('demo-final');
+};
+$(run);
+
+
+},{"ndarray":4}],2:[function(require,module,exports){
+"use strict"
+
+function iota(n) {
+  var result = new Array(n)
+  for(var i=0; i<n; ++i) {
+    result[i] = i
+  }
+  return result
+}
+
+module.exports = iota
+},{}],3:[function(require,module,exports){
+/**
+ * Determine if an object is Buffer
+ *
+ * Author:   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ * License:  MIT
+ *
+ * `npm install is-buffer`
+ */
+
+module.exports = function (obj) {
+  return !!(obj != null &&
+    (obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor)
+      (obj.constructor &&
+      typeof obj.constructor.isBuffer === 'function' &&
+      obj.constructor.isBuffer(obj))
+    ))
+}
+
+},{}],4:[function(require,module,exports){
+var iota = require("iota-array")
+var isBuffer = require("is-buffer")
+
+var hasTypedArrays  = ((typeof Float64Array) !== "undefined")
+
+function compare1st(a, b) {
+  return a[0] - b[0]
+}
+
+function order() {
+  var stride = this.stride
+  var terms = new Array(stride.length)
+  var i
+  for(i=0; i<terms.length; ++i) {
+    terms[i] = [Math.abs(stride[i]), i]
+  }
+  terms.sort(compare1st)
+  var result = new Array(terms.length)
+  for(i=0; i<result.length; ++i) {
+    result[i] = terms[i][1]
+  }
+  return result
+}
+
+function compileConstructor(dtype, dimension) {
+  var className = ["View", dimension, "d", dtype].join("")
+  if(dimension < 0) {
+    className = "View_Nil" + dtype
+  }
+  var useGetters = (dtype === "generic")
+
+  if(dimension === -1) {
+    //Special case for trivial arrays
+    var code =
+      "function "+className+"(a){this.data=a;};\
+var proto="+className+".prototype;\
+proto.dtype='"+dtype+"';\
+proto.index=function(){return -1};\
+proto.size=0;\
+proto.dimension=-1;\
+proto.shape=proto.stride=proto.order=[];\
+proto.lo=proto.hi=proto.transpose=proto.step=\
+function(){return new "+className+"(this.data);};\
+proto.get=proto.set=function(){};\
+proto.pick=function(){return null};\
+return function construct_"+className+"(a){return new "+className+"(a);}"
+    var procedure = new Function(code)
+    return procedure()
+  } else if(dimension === 0) {
+    //Special case for 0d arrays
+    var code =
+      "function "+className+"(a,d) {\
+this.data = a;\
+this.offset = d\
+};\
+var proto="+className+".prototype;\
+proto.dtype='"+dtype+"';\
+proto.index=function(){return this.offset};\
+proto.dimension=0;\
+proto.size=1;\
+proto.shape=\
+proto.stride=\
+proto.order=[];\
+proto.lo=\
+proto.hi=\
+proto.transpose=\
+proto.step=function "+className+"_copy() {\
+return new "+className+"(this.data,this.offset)\
+};\
+proto.pick=function "+className+"_pick(){\
+return TrivialArray(this.data);\
+};\
+proto.valueOf=proto.get=function "+className+"_get(){\
+return "+(useGetters ? "this.data.get(this.offset)" : "this.data[this.offset]")+
+"};\
+proto.set=function "+className+"_set(v){\
+return "+(useGetters ? "this.data.set(this.offset,v)" : "this.data[this.offset]=v")+"\
+};\
+return function construct_"+className+"(a,b,c,d){return new "+className+"(a,d)}"
+    var procedure = new Function("TrivialArray", code)
+    return procedure(CACHED_CONSTRUCTORS[dtype][0])
+  }
+
+  var code = ["'use strict'"]
+
+  //Create constructor for view
+  var indices = iota(dimension)
+  var args = indices.map(function(i) { return "i"+i })
+  var index_str = "this.offset+" + indices.map(function(i) {
+        return "this.stride[" + i + "]*i" + i
+      }).join("+")
+  var shapeArg = indices.map(function(i) {
+      return "b"+i
+    }).join(",")
+  var strideArg = indices.map(function(i) {
+      return "c"+i
+    }).join(",")
+  code.push(
+    "function "+className+"(a," + shapeArg + "," + strideArg + ",d){this.data=a",
+      "this.shape=[" + shapeArg + "]",
+      "this.stride=[" + strideArg + "]",
+      "this.offset=d|0}",
+    "var proto="+className+".prototype",
+    "proto.dtype='"+dtype+"'",
+    "proto.dimension="+dimension)
+
+  //view.size:
+  code.push("Object.defineProperty(proto,'size',{get:function "+className+"_size(){\
+return "+indices.map(function(i) { return "this.shape["+i+"]" }).join("*"),
+"}})")
+
+  //view.order:
+  if(dimension === 1) {
+    code.push("proto.order=[0]")
+  } else {
+    code.push("Object.defineProperty(proto,'order',{get:")
+    if(dimension < 4) {
+      code.push("function "+className+"_order(){")
+      if(dimension === 2) {
+        code.push("return (Math.abs(this.stride[0])>Math.abs(this.stride[1]))?[1,0]:[0,1]}})")
+      } else if(dimension === 3) {
+        code.push(
+"var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\
+if(s0>s1){\
+if(s1>s2){\
+return [2,1,0];\
+}else if(s0>s2){\
+return [1,2,0];\
+}else{\
+return [1,0,2];\
+}\
+}else if(s0>s2){\
+return [2,0,1];\
+}else if(s2>s1){\
+return [0,1,2];\
+}else{\
+return [0,2,1];\
+}}})")
+      }
+    } else {
+      code.push("ORDER})")
+    }
+  }
+
+  //view.set(i0, ..., v):
+  code.push(
+"proto.set=function "+className+"_set("+args.join(",")+",v){")
+  if(useGetters) {
+    code.push("return this.data.set("+index_str+",v)}")
+  } else {
+    code.push("return this.data["+index_str+"]=v}")
+  }
+
+  //view.get(i0, ...):
+  code.push("proto.get=function "+className+"_get("+args.join(",")+"){")
+  if(useGetters) {
+    code.push("return this.data.get("+index_str+")}")
+  } else {
+    code.push("return this.data["+index_str+"]}")
+  }
+
+  //view.index:
+  code.push(
+    "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}")
+
+  //view.hi():
+  code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+
+    indices.map(function(i) {
+      return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("")
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "this.stride["+i + "]"
+    }).join(",")+",this.offset)}")
+
+  //view.lo():
+  var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" })
+  var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" })
+  code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(","))
+  for(var i=0; i<dimension; ++i) {
+    code.push(
+"if(typeof i"+i+"==='number'&&i"+i+">=0){\
+d=i"+i+"|0;\
+b+=c"+i+"*d;\
+a"+i+"-=d}")
+  }
+  code.push("return new "+className+"(this.data,"+
+    indices.map(function(i) {
+      return "a"+i
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "c"+i
+    }).join(",")+",b)}")
+
+  //view.step():
+  code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+
+    indices.map(function(i) {
+      return "a"+i+"=this.shape["+i+"]"
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "b"+i+"=this.stride["+i+"]"
+    }).join(",")+",c=this.offset,d=0,ceil=Math.ceil")
+  for(var i=0; i<dimension; ++i) {
+    code.push(
+"if(typeof i"+i+"==='number'){\
+d=i"+i+"|0;\
+if(d<0){\
+c+=b"+i+"*(a"+i+"-1);\
+a"+i+"=ceil(-a"+i+"/d)\
+}else{\
+a"+i+"=ceil(a"+i+"/d)\
+}\
+b"+i+"*=d\
+}")
+  }
+  code.push("return new "+className+"(this.data,"+
+    indices.map(function(i) {
+      return "a" + i
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "b" + i
+    }).join(",")+",c)}")
+
+  //view.transpose():
+  var tShape = new Array(dimension)
+  var tStride = new Array(dimension)
+  for(var i=0; i<dimension; ++i) {
+    tShape[i] = "a[i"+i+"]"
+    tStride[i] = "b[i"+i+"]"
+  }
+  code.push("proto.transpose=function "+className+"_transpose("+args+"){"+
+    args.map(function(n,idx) { return n + "=(" + n + "===undefined?" + idx + ":" + n + "|0)"}).join(";"),
+    "var a=this.shape,b=this.stride;return new "+className+"(this.data,"+tShape.join(",")+","+tStride.join(",")+",this.offset)}")
+
+  //view.pick():
+  code.push("proto.pick=function "+className+"_pick("+args+"){var a=[],b=[],c=this.offset")
+  for(var i=0; i<dimension; ++i) {
+    code.push("if(typeof i"+i+"==='number'&&i"+i+">=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}")
+  }
+  code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}")
+
+  //Add return statement
+  code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+
+    indices.map(function(i) {
+      return "shape["+i+"]"
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "stride["+i+"]"
+    }).join(",")+",offset)}")
+
+  //Compile procedure
+  var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n"))
+  return procedure(CACHED_CONSTRUCTORS[dtype], order)
+}
+
+function arrayDType(data) {
+  if(isBuffer(data)) {
+    return "buffer"
+  }
+  if(hasTypedArrays) {
+    switch(Object.prototype.toString.call(data)) {
+      case "[object Float64Array]":
+        return "float64"
+      case "[object Float32Array]":
+        return "float32"
+      case "[object Int8Array]":
+        return "int8"
+      case "[object Int16Array]":
+        return "int16"
+      case "[object Int32Array]":
+        return "int32"
+      case "[object Uint8Array]":
+        return "uint8"
+      case "[object Uint16Array]":
+        return "uint16"
+      case "[object Uint32Array]":
+        return "uint32"
+      case "[object Uint8ClampedArray]":
+        return "uint8_clamped"
+    }
+  }
+  if(Array.isArray(data)) {
+    return "array"
+  }
+  return "generic"
+}
+
+var CACHED_CONSTRUCTORS = {
+  "float32":[],
+  "float64":[],
+  "int8":[],
+  "int16":[],
+  "int32":[],
+  "uint8":[],
+  "uint16":[],
+  "uint32":[],
+  "array":[],
+  "uint8_clamped":[],
+  "buffer":[],
+  "generic":[]
+}
+
+;(function() {
+  for(var id in CACHED_CONSTRUCTORS) {
+    CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1))
+  }
+});
+
+function wrappedNDArrayCtor(data, shape, stride, offset) {
+  if(data === undefined) {
+    var ctor = CACHED_CONSTRUCTORS.array[0]
+    return ctor([])
+  } else if(typeof data === "number") {
+    data = [data]
+  }
+  if(shape === undefined) {
+    shape = [ data.length ]
+  }
+  var d = shape.length
+  if(stride === undefined) {
+    stride = new Array(d)
+    for(var i=d-1, sz=1; i>=0; --i) {
+      stride[i] = sz
+      sz *= shape[i]
+    }
+  }
+  if(offset === undefined) {
+    offset = 0
+    for(var i=0; i<d; ++i) {
+      if(stride[i] < 0) {
+        offset -= (shape[i]-1)*stride[i]
+      }
+    }
+  }
+  var dtype = arrayDType(data)
+  var ctor_list = CACHED_CONSTRUCTORS[dtype]
+  while(ctor_list.length <= d+1) {
+    ctor_list.push(compileConstructor(dtype, ctor_list.length-1))
+  }
+  var ctor = ctor_list[d+1]
+  return ctor(data, shape, stride, offset)
+}
+
+module.exports = wrappedNDArrayCtor
+
+},{"iota-array":2,"is-buffer":3}]},{},[1])
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm1lZGlhL2pzL3dpc3AvYW5vbnltb3VzLndpc3AiLCJub2RlX21vZHVsZXMvaW90YS1hcnJheS9pb3RhLmpzIiwibm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9uZGFycmF5L25kYXJyYXkuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0lDQUEsSUFBQyxJLEdBQUQ7QUFBQSxRQUFBLEUsRUFBSSxNQUFKO0FBQUEsUUFBQSxHLEVBQUEsSyxDQUFBO0FBQUEsTTs7O0FBS0EsSUFBSyxLQUFBLEdBQUEsT0FBQSxDQUFBLEtBQUEsR0FBTSxHQUFYLEM7QUFDQSxJQUFLLE1BQUEsR0FBQSxPQUFBLENBQUEsTUFBQSxHQUFPLEdBQVosQztBQUNBLElBQUssU0FBQSxHQUFBLE9BQUEsQ0FBQSxTQUFBLEcsSUFBTCxDO0FBQ0EsSUFBSyxjQUFBLEdBQUEsT0FBQSxDQUFBLGNBQUEsR0FBZ0IsR0FBckIsQztBQUNBLElBQUssYUFBQSxHQUFBLE9BQUEsQ0FBQSxhQUFBLEdBQWUsRUFBcEIsQztBQUNBLElBQUssV0FBQSxHQUFBLE9BQUEsQ0FBQSxXQUFBLEdBQWEsR0FBbEIsQzs7OztBQW9CQSxJQUFNLEdBQUEsR0FBQSxPQUFBLENBQUEsR0FBQSxHQUFOLFNBQU0sR0FBTixDQUFXLENBQVgsRUFDRTtBQUFBLFdBQUcsQ0FBSCxHQUFLLENBQUw7QUFBQSxDQURGLEM7QUFHQSxJQUFNLEdBQUEsR0FBQSxPQUFBLENBQUEsR0FBQSxHQUFOLFNBQU0sR0FBTixDQUFXLENBQVgsRUFDRTtBQUFBLFdBQUcsQ0FBSCxHQUFLLENBQUw7QUFBQSxDQURGLEM7Ozs7Ozs7OztBQXdFQSxJQUFNLFFBQUEsR0FBQSxPQUFBLENBQUEsUUFBQSxHQUFOLFNBQU0sUUFBTixD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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIihucyBkZW1vXG4gICg6cmVxdWlyZSBbbmRhcnJheV0pKVxuXG5cbjsgQ29uc3RhbnRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWYgd2lkdGggNjEwKVxuKGRlZiBoZWlnaHQgNDAwKVxuKGRlZiB3aXJlZnJhbWUgdHJ1ZSlcbihkZWYgd2lyZWZyYW1lLXdpZHRoIDEuMilcbihkZWYgdGVycmFpbi1oZWlnaHQgNTApXG4oZGVmIHRlcnJhaW4tc2l6ZSAxMDApXG5cbjsgR2VuZXJhbCBVdGlsaXRpZXMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZtYWNybyB3aGVuIFtjb25kaXRpb24gJiBib2R5XVxuICBgKGlmIH5jb25kaXRpb25cbiAgICAgKGRvIH5AYm9keSkpKVxuXG4oZGVmbWFjcm8gd2hlbi1ub3QgW2NvbmRpdGlvbiAmIGJvZHldXG4gIGAod2hlbiAobm90IH5jb25kaXRpb24pXG4gICAgIH5AYm9keSkpXG5cbihkZWZtYWNybyAtPiBbJiBvcGVyYXRpb25zXVxuICAocmVkdWNlXG4gICAgKGZuIFtmb3JtIG9wZXJhdGlvbl1cbiAgICAgIChjb25zIChmaXJzdCBvcGVyYXRpb24pXG4gICAgICAgICAgICAoY29ucyBmb3JtIChyZXN0IG9wZXJhdGlvbikpKSlcbiAgICAoZmlyc3Qgb3BlcmF0aW9ucylcbiAgICAocmVzdCBvcGVyYXRpb25zKSkpXG5cblxuKGRlZm4gaW5jIFt4XVxuICAoKyB4IDEpKVxuXG4oZGVmbiBkZWMgW3hdXG4gICgtIHggMSkpXG5cblxuKGRlZm1hY3JvIGRvLXRpbWVzIFt2YXJuYW1lIGxpbWl0ICYgYm9keV1cbiAgKGxldCBbZW5kIChnZW5zeW0pXVxuICAgIGAobGV0IFt+ZW5kIH5saW1pdF1cbiAgICAgICAobG9vcCBbfnZhcm5hbWUgMF1cbiAgICAgICAgICh3aGVuICg8IH52YXJuYW1lIH5lbmQpXG4gICAgICAgICAgIH5AYm9keVxuICAgICAgICAgICAocmVjdXIgKGluYyB+dmFybmFtZSkpKSkpKSlcblxuKGRlZm1hY3JvIGRvLXN0cmlkZSBbdmFybmFtZXMgc3RhcnQtZm9ybSBlbmQtZm9ybSBzdHJpZGUtZm9ybSAmIGJvZHldXG4gIChsZXQgW3N0cmlkZSAoZ2Vuc3ltIFwic3RyaWRlXCIpXG4gICAgICAgIHN0YXJ0IChnZW5zeW0gXCJzdGFydFwiKVxuICAgICAgICBlbmQgKGdlbnN5bSBcImVuZFwiKVxuICAgICAgICBidWlsZCAoZm4gYnVpbGQgW3ZhcnNdXG4gICAgICAgICAgICAgICAgKGlmIChlbXB0eT8gdmFycylcbiAgICAgICAgICAgICAgICAgIGAoZG8gfkBib2R5KVxuICAgICAgICAgICAgICAgICAgKGxldCBbdmFybmFtZSAoZmlyc3QgdmFycyldXG4gICAgICAgICAgICAgICAgICAgIGAobG9vcCBbfnZhcm5hbWUgfnN0YXJ0XVxuICAgICAgICAgICAgICAgICAgICAgICAod2hlbiAoPCB+dmFybmFtZSB+ZW5kKVxuICAgICAgICAgICAgICAgICAgICAgICAgIH4oYnVpbGQgKHJlc3QgdmFycykpXG4gICAgICAgICAgICAgICAgICAgICAgICAgKHJlY3VyICgrIH52YXJuYW1lIH5zdHJpZGUpKSkpKSkpXVxuICAgIDsgRml4IHRoZSBudW1iZXJzIG9uY2Ugb3V0c2lkZSB0aGUgbmVzdGVkIGxvb3BzLFxuICAgIDsgYW5kIHRoZW4gYnVpbGQgdGhlIGd1dHMuXG4gICAgYChsZXQgW35zdGFydCB+c3RhcnQtZm9ybVxuICAgICAgICAgICB+ZW5kIH5lbmQtZm9ybVxuICAgICAgICAgICB+c3RyaWRlIH5zdHJpZGUtZm9ybV1cbiAgICAgICB+KGJ1aWxkIHZhcm5hbWVzKSkpKVxuXG5cbihkZWZtYWNybyBkby1uZGFycmF5IFt2YXJzIGFycmF5LWZvcm0gJiBib2R5XVxuICAobGV0IFthcnJheS12YXIgKGdlbnN5bSBcImFycmF5XCIpXG4gICAgICAgIGJ1aWxkIChmbiBidWlsZCBbdmFycyBuXVxuICAgICAgICAgICAgICAgIChpZiAoZW1wdHk/IHZhcnMpXG4gICAgICAgICAgICAgICAgICBgKGRvIH5AYm9keSlcbiAgICAgICAgICAgICAgICAgIGAoZG8tdGltZXMgfihmaXJzdCB2YXJzKSAoYWdldCAoLi1zaGFwZSB+YXJyYXktdmFyKSB+bilcbiAgICAgICAgICAgICAgICAgICAgIH4oYnVpbGQgKHJlc3QgdmFycykgKGluYyBuKSkpKSldXG4gICAgYChsZXQgW35hcnJheS12YXIgfmFycmF5LWZvcm1dXG4gICAgICAgfihidWlsZCB2YXJzIDApKSkpXG5cbihkZWZtYWNybyBkby1uZGFycmF5LWVsIFtlbGVtZW50IGFycmF5LWZvcm0gJiBib2R5XVxuICAobGV0IFtpbmRleCAoZ2Vuc3ltIFwiaW5kZXhcIilcbiAgICAgICAgYXJyYXkgKGdlbnN5bSBcImFycmF5XCIpXVxuICAgIGAobGV0IFt+YXJyYXkgfmFycmF5LWZvcm1dXG4gICAgICAgKGRvLXRpbWVzIH5pbmRleCAoLi1sZW5ndGggKC4tZGF0YSB+YXJyYXkpKVxuICAgICAgICAgKGxldCBbfmVsZW1lbnQgKGFnZXQgKC4tZGF0YSB+YXJyYXkpIH5pbmRleCldXG4gICAgICAgICAgIH5AYm9keSkpKSkpXG5cblxuKGRlZm1hY3JvIGluYyEgW3BsYWNlXVxuICBgKHNldCEgfnBsYWNlIChpbmMgfnBsYWNlKSkpXG5cbihkZWZtYWNybyBhZGQhIFtwbGFjZSBhbW91bnRdXG4gIGAoc2V0ISB+cGxhY2UgKCsgfnBsYWNlIH5hbW91bnQpKSlcblxuXG4oZGVmbWFjcm8gbCBbJiBmb3Jtc11cbiAgYChjb25zb2xlLmxvZyB+QGZvcm1zKSlcblxuKGRlZm1hY3JvIHRpbWUgWyYgYm9keV1cbiAgKGxldCBbc3RhcnQgKGdlbnN5bSlcbiAgICAgICAgZW5kIChnZW5zeW0pXG4gICAgICAgIHJlc3VsdCAoZ2Vuc3ltKV1cbiAgICBgKGxldCBbfnN0YXJ0ICguZ2V0VGltZSAobmV3IERhdGUpKVxuICAgICAgICAgICB+cmVzdWx0IChkbyB+QGJvZHkpXG4gICAgICAgICAgIH5lbmQgKC5nZXRUaW1lIChuZXcgRGF0ZSkpXVxuICAgICAgIChsICgrIFwiRWxhcHNlZCB0aW1lOiBcIiAoLSB+ZW5kIH5zdGFydCkgXCJtcy5cIikpXG4gICAgICAgfnJlc3VsdCkpKVxuXG5cbihkZWZuIG1pZHBvaW50IFthIGJdXG4gICgvICgrIGEgYikgMikpXG5cbihkZWZuIGF2ZXJhZ2UyIFthIGJdXG4gICgvICgrIGEgYikgMikpXG5cbihkZWZuIGF2ZXJhZ2U0IFthIGIgYyBkXVxuICAoLyAoKyBhIGIgYyBkKSA0KSlcblxuKGRlZm4gc2FmZS1hdmVyYWdlIFthIGIgYyBkXVxuICAobGV0IFt0b3RhbCAwIGNvdW50IDBdXG4gICAgKHdoZW4gYSAoYWRkISB0b3RhbCBhKSAoaW5jISBjb3VudCkpXG4gICAgKHdoZW4gYiAoYWRkISB0b3RhbCBiKSAoaW5jISBjb3VudCkpXG4gICAgKHdoZW4gYyAoYWRkISB0b3RhbCBjKSAoaW5jISBjb3VudCkpXG4gICAgKHdoZW4gZCAoYWRkISB0b3RhbCBkKSAoaW5jISBjb3VudCkpXG4gICAgKC8gdG90YWwgY291bnQpKSlcblxuXG4oZGVmbiBldmVuPyBbbl1cbiAgKD09IDAgKG1vZCBuIDIpKSlcblxuKGRlZm4gb2RkPyBbbl1cbiAgKD09IDEgKG1vZCBuIDIpKSlcblxuXG47IFJhbmRvbW5lc3MgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbiByYW5kIFtdXG4gIChNYXRoLnJhbmRvbSkpXG5cbihkZWZuIHJhbmQtYXJvdW5kLXplcm8gW3NwcmVhZF1cbiAgKC0gKCogc3ByZWFkIChyYW5kKSAyKSBzcHJlYWQpKVxuXG4oZGVmbiBqaXR0ZXIgW3ZhbHVlIHNwcmVhZF1cbiAgKCsgdmFsdWUgKHJhbmQtYXJvdW5kLXplcm8gc3ByZWFkKSkpXG5cblxuOyBIZWlnaHRtYXAgSGVscGVycyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gaGVpZ2h0bWFwLXJlc29sdXRpb24gW2hlaWdodG1hcF1cbiAgKGFnZXQgaGVpZ2h0bWFwLnNoYXBlIDApKVxuXG4oZGVmbiBoZWlnaHRtYXAtbGFzdC1pbmRleCBbaGVpZ2h0bWFwXVxuICAoZGVjIChoZWlnaHRtYXAtcmVzb2x1dGlvbiBoZWlnaHRtYXApKSlcblxuKGRlZm4gaGVpZ2h0bWFwLWNlbnRlci1pbmRleCBbaGVpZ2h0bWFwXVxuICAobWlkcG9pbnQgMCAoaGVpZ2h0bWFwLWxhc3QtaW5kZXggaGVpZ2h0bWFwKSkpXG5cblxuKGRlZm4gaGVpZ2h0bWFwLWdldCBbaGVpZ2h0bWFwIHggeV1cbiAgKC5nZXQgaGVpZ2h0bWFwIHggeSkpXG5cbihkZWZuIGhlaWdodG1hcC1nZXQtc2FmZSBbaGVpZ2h0bWFwIHggeV1cbiAgKGxldCBbbGFzdCAoaGVpZ2h0bWFwLWxhc3QtaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAod2hlbiAoYW5kICg8PSAwIHggbGFzdClcbiAgICAgICAgICAgICAgICg8PSAwIHkgbGFzdCkpXG4gICAgICAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgeCB5KSkpKVxuXG4oZGVmbiBoZWlnaHRtYXAtc2V0ISBbaGVpZ2h0bWFwIHggeSB2YWxdXG4gICguc2V0IGhlaWdodG1hcCB4IHkgdmFsKSlcblxuKGRlZm4gaGVpZ2h0bWFwLXNldC1pZi11bnNldCEgW2hlaWdodG1hcCB4IHkgdmFsXVxuICAod2hlbiAoPT0gMCAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgeCB5KSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIHggeSB2YWwpKSlcblxuXG4oZGVmbiBub3JtYWxpemUgW2hlaWdodG1hcF1cbiAgKGxldCBbbWF4ICgtIEluZmluaXR5KVxuICAgICAgICBtaW4gSW5maW5pdHldXG4gICAgKGRvLW5kYXJyYXktZWwgZWwgaGVpZ2h0bWFwXG4gICAgICAod2hlbiAoPCBtYXggZWwpIChzZXQhIG1heCBlbCkpXG4gICAgICAod2hlbiAoPiBtaW4gZWwpIChzZXQhIG1pbiBlbCkpKVxuICAgIChsZXQgW3NwYW4gKC0gbWF4IG1pbildXG4gICAgICAoZG8tbmRhcnJheSBbeCB5XSBoZWlnaHRtYXBcbiAgICAgICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCB4IHlcbiAgICAgICAgICAgICAgICAgICAgICAgICgvICgtIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCB4IHkpIG1pbilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4pKSkpKSlcblxuXG4oZGVmbiBtYWtlLWhlaWdodG1hcCBbZXhwb25lbnRdXG4gIChsZXQgW3Jlc29sdXRpb24gKCsgKE1hdGgucG93IDIgZXhwb25lbnQpIDEpXVxuICAgIChsZXQgW2hlaWdodG1hcCAobmRhcnJheSAobmV3IEZsb2F0NjRBcnJheSAoKiByZXNvbHV0aW9uIHJlc29sdXRpb24pKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcmVzb2x1dGlvbiByZXNvbHV0aW9uXSldXG4gICAgICAoc2V0ISBoZWlnaHRtYXAuZXhwb25lbnQgZXhwb25lbnQpXG4gICAgICAoc2V0ISBoZWlnaHRtYXAucmVzb2x1dGlvbiByZXNvbHV0aW9uKVxuICAgICAgKHNldCEgaGVpZ2h0bWFwLmxhc3QgKGRlYyByZXNvbHV0aW9uKSlcbiAgICAgIGhlaWdodG1hcCkpKVxuXG5cbihkZWZuIHRvcC1sZWZ0LWNvcm5lciBbaGVpZ2h0bWFwXVxuICAobGV0IFtjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAoLT4gaGVpZ2h0bWFwXG4gICAgICAoLmxvIDAgMClcbiAgICAgICguaGkgKGluYyBjZW50ZXIpIChpbmMgY2VudGVyKSkpKSlcblxuKGRlZm4gdG9wLXJpZ2h0LWNvcm5lciBbaGVpZ2h0bWFwXVxuICAobGV0IFtjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAoLT4gaGVpZ2h0bWFwXG4gICAgICAoLmxvIGNlbnRlciAwKVxuICAgICAgKC5oaSAoaW5jIGNlbnRlcikgKGluYyBjZW50ZXIpKSkpKVxuXG4oZGVmbiBib3R0b20tbGVmdC1jb3JuZXIgW2hlaWdodG1hcF1cbiAgKGxldCBbY2VudGVyIChoZWlnaHRtYXAtY2VudGVyLWluZGV4IGhlaWdodG1hcCldXG4gICAgKC0+IGhlaWdodG1hcFxuICAgICAgKC5sbyAwIGNlbnRlcilcbiAgICAgICguaGkgKGluYyBjZW50ZXIpIChpbmMgY2VudGVyKSkpKSlcblxuKGRlZm4gYm90dG9tLXJpZ2h0LWNvcm5lciBbaGVpZ2h0bWFwXVxuICAobGV0IFtjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAoLT4gaGVpZ2h0bWFwXG4gICAgICAoLmxvIGNlbnRlciBjZW50ZXIpXG4gICAgICAoLmhpIChpbmMgY2VudGVyKSAoaW5jIGNlbnRlcikpKSkpXG5cblxuOyBEaWFtb25kLVNxdWFyZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gZHMtaW5pdC1jb3JuZXJzIFtoZWlnaHRtYXBdXG4gIChsZXQgW2xhc3QgKGhlaWdodG1hcC1sYXN0LWluZGV4IGhlaWdodG1hcCldXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCAwICAgIDAgICAgKHJhbmQpKVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgMCAgICBsYXN0IChyYW5kKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGxhc3QgMCAgICAocmFuZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCBsYXN0IGxhc3QgKHJhbmQpKSkpXG5cbihkZWZuIGRzLXNxdWFyZSBbaGVpZ2h0bWFwIHggeSByYWRpdXMgc3ByZWFkXVxuICAobGV0IFtuZXctaGVpZ2h0IChqaXR0ZXJcbiAgICAgICAgICAgICAgICAgICAgIChhdmVyYWdlNFxuICAgICAgICAgICAgICAgICAgICAgICAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgKC0geCByYWRpdXMpICgtIHkgcmFkaXVzKSlcbiAgICAgICAgICAgICAgICAgICAgICAgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwICgtIHggcmFkaXVzKSAoKyB5IHJhZGl1cykpXG4gICAgICAgICAgICAgICAgICAgICAgIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCAoKyB4IHJhZGl1cykgKC0geSByYWRpdXMpKVxuICAgICAgICAgICAgICAgICAgICAgICAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgKCsgeCByYWRpdXMpICgrIHkgcmFkaXVzKSkpXG4gICAgICAgICAgICAgICAgICAgICBzcHJlYWQpXVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgeCB5IG5ldy1oZWlnaHQpKSlcblxuKGRlZm4gZHMtZGlhbW9uZCBbaGVpZ2h0bWFwIHggeSByYWRpdXMgc3ByZWFkXVxuICAobGV0IFtuZXctaGVpZ2h0IChqaXR0ZXJcbiAgICAgICAgICAgICAgICAgICAgIChzYWZlLWF2ZXJhZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgKGhlaWdodG1hcC1nZXQtc2FmZSBoZWlnaHRtYXAgKC0geCByYWRpdXMpIHkpXG4gICAgICAgICAgICAgICAgICAgICAgIChoZWlnaHRtYXAtZ2V0LXNhZmUgaGVpZ2h0bWFwICgrIHggcmFkaXVzKSB5KVxuICAgICAgICAgICAgICAgICAgICAgICAoaGVpZ2h0bWFwLWdldC1zYWZlIGhlaWdodG1hcCB4ICgtIHkgcmFkaXVzKSlcbiAgICAgICAgICAgICAgICAgICAgICAgKGhlaWdodG1hcC1nZXQtc2FmZSBoZWlnaHRtYXAgeCAoKyB5IHJhZGl1cykpKVxuICAgICAgICAgICAgICAgICAgICAgc3ByZWFkKV1cbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIHggeSBuZXctaGVpZ2h0KSkpXG5cblxuKGRlZm4gZHMtc3F1YXJlcyBbaGVpZ2h0bWFwIHJhZGl1cyBzcHJlYWRdXG4gIChkby1zdHJpZGUgW3ggeV0gcmFkaXVzIChoZWlnaHRtYXAtcmVzb2x1dGlvbiBoZWlnaHRtYXApICgqIDIgcmFkaXVzKVxuICAgIChkcy1zcXVhcmUgaGVpZ2h0bWFwIHggeSByYWRpdXMgc3ByZWFkKSkpXG5cbihkZWZuIGRzLWRpYW1vbmRzIFtoZWlnaHRtYXAgcmFkaXVzIHNwcmVhZF1cbiAgKGxldCBbc2l6ZSAoaGVpZ2h0bWFwLXJlc29sdXRpb24gaGVpZ2h0bWFwKV1cbiAgICAoZG8tc3RyaWRlIFt5XSAwIHNpemUgcmFkaXVzXG4gICAgICAobGV0IFtzaGlmdCAoaWYgKGV2ZW4/ICgvIHkgcmFkaXVzKSkgcmFkaXVzIDApXVxuICAgICAgICAoZG8tc3RyaWRlIFt4XSBzaGlmdCBzaXplICgqIDIgcmFkaXVzKVxuICAgICAgICAgIChkcy1kaWFtb25kIGhlaWdodG1hcCB4IHkgcmFkaXVzIHNwcmVhZCkpKSkpKVxuXG4oZGVmbiBkaWFtb25kLXNxdWFyZSBbaGVpZ2h0bWFwXVxuICAobGV0IFtpbml0aWFsLXNwcmVhZCAwLjNcbiAgICAgICAgc3ByZWFkLXJlZHVjdGlvbiAwLjVcbiAgICAgICAgY2VudGVyIChoZWlnaHRtYXAtY2VudGVyLWluZGV4IGhlaWdodG1hcClcbiAgICAgICAgc2l6ZSAoYWdldCBoZWlnaHRtYXAuc2hhcGUgMCldXG4gICAgKGRzLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gICAgKGxvb3AgW3JhZGl1cyBjZW50ZXJcbiAgICAgICAgICAgc3ByZWFkIGluaXRpYWwtc3ByZWFkXVxuICAgICAgKHdoZW4gKD49IHJhZGl1cyAxKVxuICAgICAgICAoZHMtc3F1YXJlcyBoZWlnaHRtYXAgcmFkaXVzIHNwcmVhZClcbiAgICAgICAgKGRzLWRpYW1vbmRzIGhlaWdodG1hcCByYWRpdXMgc3ByZWFkKVxuICAgICAgICAocmVjdXIgKC8gcmFkaXVzIDIpXG4gICAgICAgICAgICAgICAoKiBzcHJlYWQgc3ByZWFkLXJlZHVjdGlvbikpKSlcbiAgICAobm9ybWFsaXplIGhlaWdodG1hcCkpKVxuXG5cbihkZWZuIGRpYW1vbmQtc3F1YXJlLTEgW2hlaWdodG1hcF1cbiAgKGRzLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gIChub3JtYWxpemUgaGVpZ2h0bWFwKSlcblxuKGRlZm4gZGlhbW9uZC1zcXVhcmUtMiBbaGVpZ2h0bWFwXVxuICAobGV0IFtpbml0aWFsLXNwcmVhZCAwLjNcbiAgICAgICAgc3ByZWFkLXJlZHVjdGlvbiAwLjVcbiAgICAgICAgY2VudGVyIChoZWlnaHRtYXAtY2VudGVyLWluZGV4IGhlaWdodG1hcClcbiAgICAgICAgc2l6ZSAoYWdldCBoZWlnaHRtYXAuc2hhcGUgMCldXG4gICAgKGRzLWluaXQtY29ybmVycyBoZWlnaHRtYXApXG4gICAgKGRzLXNxdWFyZXMgaGVpZ2h0bWFwIGNlbnRlciBpbml0aWFsLXNwcmVhZClcbiAgICAobm9ybWFsaXplIGhlaWdodG1hcCkpKVxuXG4oZGVmbiBkaWFtb25kLXNxdWFyZS0zIFtoZWlnaHRtYXBdXG4gIChsZXQgW2luaXRpYWwtc3ByZWFkIDAuM1xuICAgICAgICBzcHJlYWQtcmVkdWN0aW9uIDAuNVxuICAgICAgICBjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKVxuICAgICAgICBzaXplIChhZ2V0IGhlaWdodG1hcC5zaGFwZSAwKV1cbiAgICAoZHMtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgICAoZHMtc3F1YXJlcyBoZWlnaHRtYXAgY2VudGVyIGluaXRpYWwtc3ByZWFkKVxuICAgIChkcy1kaWFtb25kcyBoZWlnaHRtYXAgY2VudGVyIGluaXRpYWwtc3ByZWFkKVxuICAgIChkcy1zcXVhcmVzIGhlaWdodG1hcCAoLyBjZW50ZXIgMikgKCogc3ByZWFkLXJlZHVjdGlvbiBpbml0aWFsLXNwcmVhZCkpXG4gICAgKGRzLWRpYW1vbmRzIGhlaWdodG1hcCAoLyBjZW50ZXIgMikgKCogc3ByZWFkLXJlZHVjdGlvbiBpbml0aWFsLXNwcmVhZCkpXG4gICAgKG5vcm1hbGl6ZSBoZWlnaHRtYXApKSlcblxuXG47IFRocmVlLmpzIEhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbiBtYWtlLWRpcmVjdGlvbmFsLWxpZ2h0IFtdXG4gIChsZXQgW2xpZ2h0IChuZXcgVEhSRUUuRGlyZWN0aW9uYWxMaWdodCAweGZmZmZmZiAxKV1cbiAgICAobGlnaHQucG9zaXRpb24uc2V0IDEwMCAwIDE1MClcbiAgICBsaWdodCkpXG5cbihkZWZuIG1ha2UtY2FtZXJhIFtdXG4gIChsZXQgW2NhbWVyYSAobmV3IFRIUkVFLlBlcnNwZWN0aXZlQ2FtZXJhXG4gICAgICAgICAgICAgICAgICAgIDU1LFxuICAgICAgICAgICAgICAgICAgICAoLyB3aWR0aCBoZWlnaHQpXG4gICAgICAgICAgICAgICAgICAgIDAuMSxcbiAgICAgICAgICAgICAgICAgICAgMTAwMCldXG4gICAgKGNhbWVyYS5wb3NpdGlvbi5zZXQgMCAtMTAwIDE1MClcbiAgICBjYW1lcmEpKVxuXG4oZGVmbiBtYWtlLXJlbmRlcmVyIFtdXG4gIChsZXQgW3JlbmRlcmVyIChuZXcgVEhSRUUuV2ViR0xSZW5kZXJlciB7OmFudGlhbGlhcyBmYWxzZX0pXVxuICAgIChyZW5kZXJlci5zZXRDbGVhckNvbG9yIDB4ZmZmZmZmKVxuICAgIChyZW5kZXJlci5zZXRTaXplIHdpZHRoIGhlaWdodClcbiAgICAocmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyAyKVxuICAgIHJlbmRlcmVyKSlcblxuKGRlZm4gbWFrZS1nZW9tZXRyeSBbaGVpZ2h0bWFwXVxuICAobGV0IFtyZXNvbHV0aW9uIChhZ2V0IGhlaWdodG1hcC5zaGFwZSAwKVxuICAgICAgICBnZW9tZXRyeSAobmV3IFRIUkVFLlBsYW5lR2VvbWV0cnlcbiAgICAgICAgICAgICAgICAgICAgICB0ZXJyYWluLXNpemVcbiAgICAgICAgICAgICAgICAgICAgICB0ZXJyYWluLXNpemVcbiAgICAgICAgICAgICAgICAgICAgICAoLSByZXNvbHV0aW9uIDEpXG4gICAgICAgICAgICAgICAgICAgICAgKC0gcmVzb2x1dGlvbiAxKSldXG4gICAgZ2VvbWV0cnkpKVxuXG4oZGVmbiBtYWtlLWNvbnRyb2xzIFtjYW1lcmEgcmVuZGVyZXJdXG4gIChsZXQgW2NvbnRyb2xzIChuZXcgVEhSRUUuVHJhY2tiYWxsQ29udHJvbHMgY2FtZXJhIHJlbmRlcmVyLmRvbUVsZW1lbnQpXVxuICAgIChzZXQhIGNvbnRyb2xzLnJvdGF0ZVNwZWVkIDEuNClcbiAgICAoc2V0ISBjb250cm9scy56b29tU3BlZWQgMC41KVxuICAgIChzZXQhIGNvbnRyb2xzLnN0YXRpY01vdmluZyB0cnVlKVxuICAgIChzZXQhIGNvbnRyb2xzLmR5bmFtaWNEYW1waW5nRmFjdG9yIDAuMylcbiAgICBjb250cm9scykpXG5cbihkZWZuIG1ha2UtcGxhbmUgW2dlb21ldHJ5XVxuICAobGV0IFttYXRlcmlhbCAobmV3IFRIUkVFLk1lc2hMYW1iZXJ0TWF0ZXJpYWxcbiAgICAgICAgICAgICAgICAgICAgICB7OndpcmVmcmFtZSB3aXJlZnJhbWVcbiAgICAgICAgICAgICAgICAgICAgICAgOndpcmVmcmFtZUxpbmV3aWR0aCB3aXJlZnJhbWUtd2lkdGhcbiAgICAgICAgICAgICAgICAgICAgICAgOmNvbG9yIDB4MDBiYjAwfSldXG4gICAgKG5ldyBUSFJFRS5NZXNoIGdlb21ldHJ5IG1hdGVyaWFsKSkpXG5cblxuKGRlZm4gYXR0YWNoLXRvLWRvbSBbcmVuZGVyZXIgZWwtbmFtZSByZWZyZXNoLWZuXVxuICAobGV0IFtjb250YWluZXIgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkIGVsLW5hbWUpXG4gICAgICAgIHNldHRpbmdzIChkb2N1bWVudC5jcmVhdGVFbGVtZW50IFwiZGl2XCIpXG4gICAgICAgIHJlZnJlc2gtYnV0dG9uIChkb2N1bWVudC5jcmVhdGVFbGVtZW50IFwiYnV0dG9uXCIpXG4gICAgICAgIGJ1dHRvbi10ZXh0IChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSBcIlJlZnJlc2hcIilcbiAgICAgICAgY2FuY2VsLXNjcm9sbCAoZm4gW2VdICgucHJldmVudERlZmF1bHQgZSkpXVxuICAgIChzZXQhIHJlZnJlc2gtYnV0dG9uLm9uY2xpY2sgcmVmcmVzaC1mbilcbiAgICAoc2V0ISByZW5kZXJlci5kb21FbGVtZW50Lm9ubW91c2V3aGVlbCBjYW5jZWwtc2Nyb2xsKVxuICAgIChyZW5kZXJlci5kb21FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIgXCJNb3pNb3VzZVBpeGVsU2Nyb2xsXCIgY2FuY2VsLXNjcm9sbCBmYWxzZSlcbiAgICAoLmFwcGVuZENoaWxkIHJlZnJlc2gtYnV0dG9uIGJ1dHRvbi10ZXh0KVxuICAgICguYXBwZW5kQ2hpbGQgY29udGFpbmVyIHJlbmRlcmVyLmRvbUVsZW1lbnQpXG4gICAgKC5hcHBlbmRDaGlsZCBjb250YWluZXIgc2V0dGluZ3MpXG4gICAgKC5hcHBlbmRDaGlsZCBzZXR0aW5ncyByZWZyZXNoLWJ1dHRvbikpKVxuXG5cbihkZWZuIHVwZGF0ZS1nZW9tZXRyeSBbZ2VvbWV0cnkgaGVpZ2h0bWFwXVxuICAobG9vcCBbaSAwXVxuICAgIChpZiAoPCBpIGdlb21ldHJ5LnZlcnRpY2VzLmxlbmd0aClcbiAgICAgIChkbyAoc2V0ISAoLi16IChhZ2V0IGdlb21ldHJ5LnZlcnRpY2VzIGkpKVxuICAgICAgICAgICAgICAgICgqIHRlcnJhaW4taGVpZ2h0IChhZ2V0ICguLWRhdGEgaGVpZ2h0bWFwKSBpKSkpXG4gICAgICAgIChyZWN1ciAoKyBpIDEpKSkpKVxuICAoZ2VvbWV0cnkuY29tcHV0ZVZlcnRleE5vcm1hbHMpXG4gIGdlb21ldHJ5KVxuXG5cbjsgTWFpbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIG1ha2UtZGVtbyBbZWxlbWVudC1pZCBhbGdvcml0aG0gc2l6ZV1cbiAgKGRlZiBzY2VuZSAobmV3IFRIUkVFLlNjZW5lKSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkF4aXNIZWxwZXIgMTAwKSlcblxuICAoZGVmIGNsb2NrIChuZXcgVEhSRUUuQ2xvY2spKVxuICAoZGVmIGNhbWVyYSAobWFrZS1jYW1lcmEpKVxuICAoZGVmIHJlbmRlcmVyIChtYWtlLXJlbmRlcmVyKSlcblxuICAoZGVmIGdlb21ldHJ5KVxuICAoZGVmIHBsYW5lKVxuXG4gIChzY2VuZS5hZGQgKG1ha2UtZGlyZWN0aW9uYWwtbGlnaHQpKVxuICAoc2NlbmUuYWRkIChuZXcgVEhSRUUuQW1iaWVudExpZ2h0IDB4ZmZmZmZmIDAuMDUpKVxuXG4gIChkZWZuIHJlZnJlc2ggW11cbiAgICAobGV0IFtoZWlnaHRtYXAgKG1ha2UtaGVpZ2h0bWFwIHNpemUpXVxuICAgICAgKGwgXCJHZW5lcmF0aW5nIHRlcnJhaW4uLi5cIilcbiAgICAgICh0aW1lIChhbGdvcml0aG0gaGVpZ2h0bWFwKSlcblxuICAgICAgKGwgXCJSZWJ1aWxkaW5nIGdlb21ldHJ5Li4uXCIpXG4gICAgICAodGltZVxuICAgICAgICAoc2V0ISBnZW9tZXRyeSAobWFrZS1nZW9tZXRyeSBoZWlnaHRtYXApKVxuICAgICAgICAodXBkYXRlLWdlb21ldHJ5IGdlb21ldHJ5IGhlaWdodG1hcCkpXG5cbiAgICAgIChsIFwiUmVidWlsZGluZyBwbGFuZS4uLlwiKVxuICAgICAgKHRpbWVcbiAgICAgICAgKHNjZW5lLnJlbW92ZSBwbGFuZSlcbiAgICAgICAgKHNldCEgcGxhbmUgKG1ha2UtcGxhbmUgZ2VvbWV0cnkpKVxuICAgICAgICAoc2NlbmUuYWRkIHBsYW5lKSkpKVxuXG4gIChhdHRhY2gtdG8tZG9tIHJlbmRlcmVyIGVsZW1lbnQtaWQgcmVmcmVzaClcbiAgKGRlZiBjb250cm9scyAobWFrZS1jb250cm9scyBjYW1lcmEgcmVuZGVyZXIpKVxuXG4gIChkZWZuIHJlbmRlciBbXVxuICAgIChsZXQgW2RlbHRhIChjbG9jay5nZXREZWx0YSldXG4gICAgICAocmVxdWVzdEFuaW1hdGlvbkZyYW1lIHJlbmRlcilcbiAgICAgICgudXBkYXRlIGNvbnRyb2xzIGRlbHRhKVxuICAgICAgKHJlbmRlcmVyLnJlbmRlciBzY2VuZSBjYW1lcmEpKSlcblxuICAocmVmcmVzaClcbiAgKHJlbmRlcilcblxuICBuaWwpXG5cbihkZWZuIG1ha2UtZmluYWwgW2VsZW1lbnQtaWRdXG4gIChkZWYgc2NlbmUgKG5ldyBUSFJFRS5TY2VuZSkpXG4gIChzY2VuZS5hZGQgKG5ldyBUSFJFRS5BeGlzSGVscGVyIDEwMCkpXG5cbiAgKGRlZiBjbG9jayAobmV3IFRIUkVFLkNsb2NrKSlcbiAgKGRlZiBjYW1lcmEgKG1ha2UtY2FtZXJhKSlcbiAgKGRlZiByZW5kZXJlciAobWFrZS1yZW5kZXJlcikpXG5cbiAgKGRlZiBnZW9tZXRyeSlcbiAgKGRlZiBwbGFuZSlcblxuICAoc2NlbmUuYWRkIChtYWtlLWRpcmVjdGlvbmFsLWxpZ2h0KSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkFtYmllbnRMaWdodCAweGZmZmZmZiAwLjA1KSlcblxuICAoZGVmbiByZWZyZXNoIFtdXG4gICAgKGxldCBbaGVpZ2h0bWFwIChtYWtlLWhlaWdodG1hcCA2KV1cbiAgICAgIChsIFwiR2VuZXJhdGluZyB0ZXJyYWluLi4uXCIpXG4gICAgICAodGltZSAoZGlhbW9uZC1zcXVhcmUgaGVpZ2h0bWFwKSlcblxuICAgICAgKGwgXCJSZWJ1aWxkaW5nIGdlb21ldHJ5Li4uXCIpXG4gICAgICAodGltZVxuICAgICAgICAoc2V0ISBnZW9tZXRyeSAobWFrZS1nZW9tZXRyeSBoZWlnaHRtYXApKVxuICAgICAgICAodXBkYXRlLWdlb21ldHJ5IGdlb21ldHJ5IGhlaWdodG1hcCkpXG5cbiAgICAgIChsIFwiUmVidWlsZGluZyBwbGFuZS4uLlwiKVxuICAgICAgKHRpbWVcbiAgICAgICAgKHNjZW5lLnJlbW92ZSBwbGFuZSlcbiAgICAgICAgKHNldCEgcGxhbmUgKG1ha2UtcGxhbmUgZ2VvbWV0cnkpKVxuICAgICAgICAoc2NlbmUuYWRkIHBsYW5lKSkpKVxuXG4gIChhdHRhY2gtdG8tZG9tIHJlbmRlcmVyIGVsZW1lbnQtaWQgcmVmcmVzaClcbiAgKGRlZiBjb250cm9scyAobWFrZS1jb250cm9scyBjYW1lcmEgcmVuZGVyZXIpKVxuXG4gIChkZWZuIHJlbmRlciBbXVxuICAgIChsZXQgW2RlbHRhIChjbG9jay5nZXREZWx0YSldXG4gICAgICAocmVxdWVzdEFuaW1hdGlvbkZyYW1lIHJlbmRlcilcbiAgICAgICgudXBkYXRlIGNvbnRyb2xzIGRlbHRhKVxuICAgICAgKHJlbmRlcmVyLnJlbmRlciBzY2VuZSBjYW1lcmEpKSlcblxuICAocmVmcmVzaClcbiAgKHJlbmRlcilcblxuICBuaWwpXG5cbihkZWZuIHJ1biBbXVxuICAobWFrZS1kZW1vIFwiZGVtby0xXCIgZGlhbW9uZC1zcXVhcmUtMSAyKVxuICAobWFrZS1kZW1vIFwiZGVtby0yXCIgZGlhbW9uZC1zcXVhcmUtMiA0KVxuICAobWFrZS1kZW1vIFwiZGVtby0zXCIgZGlhbW9uZC1zcXVhcmUtMyA0KVxuICAobWFrZS1maW5hbCBcImRlbW8tZmluYWxcIikpXG5cbigkIHJ1bilcblxuXG47IHZpbTogbHcrPWRvLXRpbWVzIGx3Kz1kby1uZXN0ZWQgOlxuIiwiXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gaW90YShuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gaVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpb3RhIiwiLyoqXG4gKiBEZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIEJ1ZmZlclxuICpcbiAqIEF1dGhvcjogICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogTGljZW5zZTogIE1JVFxuICpcbiAqIGBucG0gaW5zdGFsbCBpcy1idWZmZXJgXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiAhIShvYmogIT0gbnVsbCAmJlxuICAgIChvYmouX2lzQnVmZmVyIHx8IC8vIEZvciBTYWZhcmkgNS03IChtaXNzaW5nIE9iamVjdC5wcm90b3R5cGUuY29uc3RydWN0b3IpXG4gICAgICAob2JqLmNvbnN0cnVjdG9yICYmXG4gICAgICB0eXBlb2Ygb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyID09PSAnZnVuY3Rpb24nICYmXG4gICAgICBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIob2JqKSlcbiAgICApKVxufVxuIiwidmFyIGlvdGEgPSByZXF1aXJlKFwiaW90YS1hcnJheVwiKVxudmFyIGlzQnVmZmVyID0gcmVxdWlyZShcImlzLWJ1ZmZlclwiKVxuXG52YXIgaGFzVHlwZWRBcnJheXMgID0gKCh0eXBlb2YgRmxvYXQ2NEFycmF5KSAhPT0gXCJ1bmRlZmluZWRcIilcblxuZnVuY3Rpb24gY29tcGFyZTFzdChhLCBiKSB7XG4gIHJldHVybiBhWzBdIC0gYlswXVxufVxuXG5mdW5jdGlvbiBvcmRlcigpIHtcbiAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlXG4gIHZhciB0ZXJtcyA9IG5ldyBBcnJheShzdHJpZGUubGVuZ3RoKVxuICB2YXIgaVxuICBmb3IoaT0wOyBpPHRlcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgdGVybXNbaV0gPSBbTWF0aC5hYnMoc3RyaWRlW2ldKSwgaV1cbiAgfVxuICB0ZXJtcy5zb3J0KGNvbXBhcmUxc3QpXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkodGVybXMubGVuZ3RoKVxuICBmb3IoaT0wOyBpPHJlc3VsdC5sZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IHRlcm1zW2ldWzFdXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGRpbWVuc2lvbikge1xuICB2YXIgY2xhc3NOYW1lID0gW1wiVmlld1wiLCBkaW1lbnNpb24sIFwiZFwiLCBkdHlwZV0uam9pbihcIlwiKVxuICBpZihkaW1lbnNpb24gPCAwKSB7XG4gICAgY2xhc3NOYW1lID0gXCJWaWV3X05pbFwiICsgZHR5cGVcbiAgfVxuICB2YXIgdXNlR2V0dGVycyA9IChkdHlwZSA9PT0gXCJnZW5lcmljXCIpXG5cbiAgaWYoZGltZW5zaW9uID09PSAtMSkge1xuICAgIC8vU3BlY2lhbCBjYXNlIGZvciB0cml2aWFsIGFycmF5c1xuICAgIHZhciBjb2RlID1cbiAgICAgIFwiZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiKGEpe3RoaXMuZGF0YT1hO307XFxcbnZhciBwcm90bz1cIitjbGFzc05hbWUrXCIucHJvdG90eXBlO1xcXG5wcm90by5kdHlwZT0nXCIrZHR5cGUrXCInO1xcXG5wcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiAtMX07XFxcbnByb3RvLnNpemU9MDtcXFxucHJvdG8uZGltZW5zaW9uPS0xO1xcXG5wcm90by5zaGFwZT1wcm90by5zdHJpZGU9cHJvdG8ub3JkZXI9W107XFxcbnByb3RvLmxvPXByb3RvLmhpPXByb3RvLnRyYW5zcG9zZT1wcm90by5zdGVwPVxcXG5mdW5jdGlvbigpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKHRoaXMuZGF0YSk7fTtcXFxucHJvdG8uZ2V0PXByb3RvLnNldD1mdW5jdGlvbigpe307XFxcbnByb3RvLnBpY2s9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH07XFxcbnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfXCIrY2xhc3NOYW1lK1wiKGEpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKGEpO31cIlxuICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oY29kZSlcbiAgICByZXR1cm4gcHJvY2VkdXJlKClcbiAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMCkge1xuICAgIC8vU3BlY2lhbCBjYXNlIGZvciAwZCBhcnJheXNcbiAgICB2YXIgY29kZSA9XG4gICAgICBcImZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIihhLGQpIHtcXFxudGhpcy5kYXRhID0gYTtcXFxudGhpcy5vZmZzZXQgPSBkXFxcbn07XFxcbnZhciBwcm90bz1cIitjbGFzc05hbWUrXCIucHJvdG90eXBlO1xcXG5wcm90by5kdHlwZT0nXCIrZHR5cGUrXCInO1xcXG5wcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm9mZnNldH07XFxcbnByb3RvLmRpbWVuc2lvbj0wO1xcXG5wcm90by5zaXplPTE7XFxcbnByb3RvLnNoYXBlPVxcXG5wcm90by5zdHJpZGU9XFxcbnByb3RvLm9yZGVyPVtdO1xcXG5wcm90by5sbz1cXFxucHJvdG8uaGk9XFxcbnByb3RvLnRyYW5zcG9zZT1cXFxucHJvdG8uc3RlcD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfY29weSgpIHtcXFxucmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLHRoaXMub2Zmc2V0KVxcXG59O1xcXG5wcm90by5waWNrPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9waWNrKCl7XFxcbnJldHVybiBUcml2aWFsQXJyYXkodGhpcy5kYXRhKTtcXFxufTtcXFxucHJvdG8udmFsdWVPZj1wcm90by5nZXQ9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2dldCgpe1xcXG5yZXR1cm4gXCIrKHVzZUdldHRlcnMgPyBcInRoaXMuZGF0YS5nZXQodGhpcy5vZmZzZXQpXCIgOiBcInRoaXMuZGF0YVt0aGlzLm9mZnNldF1cIikrXG5cIn07XFxcbnByb3RvLnNldD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfc2V0KHYpe1xcXG5yZXR1cm4gXCIrKHVzZUdldHRlcnMgPyBcInRoaXMuZGF0YS5zZXQodGhpcy5vZmZzZXQsdilcIiA6IFwidGhpcy5kYXRhW3RoaXMub2Zmc2V0XT12XCIpK1wiXFxcbn07XFxcbnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfXCIrY2xhc3NOYW1lK1wiKGEsYixjLGQpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKGEsZCl9XCJcbiAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKFwiVHJpdmlhbEFycmF5XCIsIGNvZGUpXG4gICAgcmV0dXJuIHByb2NlZHVyZShDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXVswXSlcbiAgfVxuXG4gIHZhciBjb2RlID0gW1wiJ3VzZSBzdHJpY3QnXCJdXG5cbiAgLy9DcmVhdGUgY29uc3RydWN0b3IgZm9yIHZpZXdcbiAgdmFyIGluZGljZXMgPSBpb3RhKGRpbWVuc2lvbilcbiAgdmFyIGFyZ3MgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcImlcIitpIH0pXG4gIHZhciBpbmRleF9zdHIgPSBcInRoaXMub2Zmc2V0K1wiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgICByZXR1cm4gXCJ0aGlzLnN0cmlkZVtcIiArIGkgKyBcIl0qaVwiICsgaVxuICAgICAgfSkuam9pbihcIitcIilcbiAgdmFyIHNoYXBlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiYlwiK2lcbiAgICB9KS5qb2luKFwiLFwiKVxuICB2YXIgc3RyaWRlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiY1wiK2lcbiAgICB9KS5qb2luKFwiLFwiKVxuICBjb2RlLnB1c2goXG4gICAgXCJmdW5jdGlvbiBcIitjbGFzc05hbWUrXCIoYSxcIiArIHNoYXBlQXJnICsgXCIsXCIgKyBzdHJpZGVBcmcgKyBcIixkKXt0aGlzLmRhdGE9YVwiLFxuICAgICAgXCJ0aGlzLnNoYXBlPVtcIiArIHNoYXBlQXJnICsgXCJdXCIsXG4gICAgICBcInRoaXMuc3RyaWRlPVtcIiArIHN0cmlkZUFyZyArIFwiXVwiLFxuICAgICAgXCJ0aGlzLm9mZnNldD1kfDB9XCIsXG4gICAgXCJ2YXIgcHJvdG89XCIrY2xhc3NOYW1lK1wiLnByb3RvdHlwZVwiLFxuICAgIFwicHJvdG8uZHR5cGU9J1wiK2R0eXBlK1wiJ1wiLFxuICAgIFwicHJvdG8uZGltZW5zaW9uPVwiK2RpbWVuc2lvbilcblxuICAvL3ZpZXcuc2l6ZTpcbiAgY29kZS5wdXNoKFwiT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCdzaXplJyx7Z2V0OmZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9zaXplKCl7XFxcbnJldHVybiBcIitpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcInRoaXMuc2hhcGVbXCIraStcIl1cIiB9KS5qb2luKFwiKlwiKSxcblwifX0pXCIpXG5cbiAgLy92aWV3Lm9yZGVyOlxuICBpZihkaW1lbnNpb24gPT09IDEpIHtcbiAgICBjb2RlLnB1c2goXCJwcm90by5vcmRlcj1bMF1cIilcbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goXCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ29yZGVyJyx7Z2V0OlwiKVxuICAgIGlmKGRpbWVuc2lvbiA8IDQpIHtcbiAgICAgIGNvZGUucHVzaChcImZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9vcmRlcigpe1wiKVxuICAgICAgaWYoZGltZW5zaW9uID09PSAyKSB7XG4gICAgICAgIGNvZGUucHVzaChcInJldHVybiAoTWF0aC5hYnModGhpcy5zdHJpZGVbMF0pPk1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSk/WzEsMF06WzAsMV19fSlcIilcbiAgICAgIH0gZWxzZSBpZihkaW1lbnNpb24gPT09IDMpIHtcbiAgICAgICAgY29kZS5wdXNoKFxuXCJ2YXIgczA9TWF0aC5hYnModGhpcy5zdHJpZGVbMF0pLHMxPU1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSxzMj1NYXRoLmFicyh0aGlzLnN0cmlkZVsyXSk7XFxcbmlmKHMwPnMxKXtcXFxuaWYoczE+czIpe1xcXG5yZXR1cm4gWzIsMSwwXTtcXFxufWVsc2UgaWYoczA+czIpe1xcXG5yZXR1cm4gWzEsMiwwXTtcXFxufWVsc2V7XFxcbnJldHVybiBbMSwwLDJdO1xcXG59XFxcbn1lbHNlIGlmKHMwPnMyKXtcXFxucmV0dXJuIFsyLDAsMV07XFxcbn1lbHNlIGlmKHMyPnMxKXtcXFxucmV0dXJuIFswLDEsMl07XFxcbn1lbHNle1xcXG5yZXR1cm4gWzAsMiwxXTtcXFxufX19KVwiKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goXCJPUkRFUn0pXCIpXG4gICAgfVxuICB9XG5cbiAgLy92aWV3LnNldChpMCwgLi4uLCB2KTpcbiAgY29kZS5wdXNoKFxuXCJwcm90by5zZXQ9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3NldChcIithcmdzLmpvaW4oXCIsXCIpK1wiLHYpe1wiKVxuICBpZih1c2VHZXR0ZXJzKSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIHRoaXMuZGF0YS5zZXQoXCIraW5kZXhfc3RyK1wiLHYpfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcInJldHVybiB0aGlzLmRhdGFbXCIraW5kZXhfc3RyK1wiXT12fVwiKVxuICB9XG5cbiAgLy92aWV3LmdldChpMCwgLi4uKTpcbiAgY29kZS5wdXNoKFwicHJvdG8uZ2V0PWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9nZXQoXCIrYXJncy5qb2luKFwiLFwiKStcIil7XCIpXG4gIGlmKHVzZUdldHRlcnMpIHtcbiAgICBjb2RlLnB1c2goXCJyZXR1cm4gdGhpcy5kYXRhLmdldChcIitpbmRleF9zdHIrXCIpfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcInJldHVybiB0aGlzLmRhdGFbXCIraW5kZXhfc3RyK1wiXX1cIilcbiAgfVxuXG4gIC8vdmlldy5pbmRleDpcbiAgY29kZS5wdXNoKFxuICAgIFwicHJvdG8uaW5kZXg9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2luZGV4KFwiLCBhcmdzLmpvaW4oKSwgXCIpe3JldHVybiBcIitpbmRleF9zdHIrXCJ9XCIpXG5cbiAgLy92aWV3LmhpKCk6XG4gIGNvZGUucHVzaChcInByb3RvLmhpPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9oaShcIithcmdzLmpvaW4oXCIsXCIpK1wiKXtyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFtcIih0eXBlb2YgaVwiLGksXCIhPT0nbnVtYmVyJ3x8aVwiLGksXCI8MCk/dGhpcy5zaGFwZVtcIiwgaSwgXCJdOmlcIiwgaSxcInwwXCJdLmpvaW4oXCJcIilcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJ0aGlzLnN0cmlkZVtcIitpICsgXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIix0aGlzLm9mZnNldCl9XCIpXG5cbiAgLy92aWV3LmxvKCk6XG4gIHZhciBhX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcImFcIitpK1wiPXRoaXMuc2hhcGVbXCIraStcIl1cIiB9KVxuICB2YXIgY192YXJzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gXCJjXCIraStcIj10aGlzLnN0cmlkZVtcIitpK1wiXVwiIH0pXG4gIGNvZGUucHVzaChcInByb3RvLmxvPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9sbyhcIithcmdzLmpvaW4oXCIsXCIpK1wiKXt2YXIgYj10aGlzLm9mZnNldCxkPTAsXCIrYV92YXJzLmpvaW4oXCIsXCIpK1wiLFwiK2NfdmFycy5qb2luKFwiLFwiKSlcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXG5cImlmKHR5cGVvZiBpXCIraStcIj09PSdudW1iZXInJiZpXCIraStcIj49MCl7XFxcbmQ9aVwiK2krXCJ8MDtcXFxuYis9Y1wiK2krXCIqZDtcXFxuYVwiK2krXCItPWR9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwicmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImFcIitpXG4gICAgfSkuam9pbihcIixcIikrXCIsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiY1wiK2lcbiAgICB9KS5qb2luKFwiLFwiKStcIixiKX1cIilcblxuICAvL3ZpZXcuc3RlcCgpOlxuICBjb2RlLnB1c2goXCJwcm90by5zdGVwPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9zdGVwKFwiK2FyZ3Muam9pbihcIixcIikrXCIpe3ZhciBcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJhXCIraStcIj10aGlzLnNoYXBlW1wiK2krXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJiXCIraStcIj10aGlzLnN0cmlkZVtcIitpK1wiXVwiXG4gICAgfSkuam9pbihcIixcIikrXCIsYz10aGlzLm9mZnNldCxkPTAsY2VpbD1NYXRoLmNlaWxcIilcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXG5cImlmKHR5cGVvZiBpXCIraStcIj09PSdudW1iZXInKXtcXFxuZD1pXCIraStcInwwO1xcXG5pZihkPDApe1xcXG5jKz1iXCIraStcIiooYVwiK2krXCItMSk7XFxcbmFcIitpK1wiPWNlaWwoLWFcIitpK1wiL2QpXFxcbn1lbHNle1xcXG5hXCIraStcIj1jZWlsKGFcIitpK1wiL2QpXFxcbn1cXFxuYlwiK2krXCIqPWRcXFxufVwiKVxuICB9XG4gIGNvZGUucHVzaChcInJldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKHRoaXMuZGF0YSxcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJhXCIgKyBpXG4gICAgfSkuam9pbihcIixcIikrXCIsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiYlwiICsgaVxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLGMpfVwiKVxuXG4gIC8vdmlldy50cmFuc3Bvc2UoKTpcbiAgdmFyIHRTaGFwZSA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gIHZhciB0U3RyaWRlID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICB0U2hhcGVbaV0gPSBcImFbaVwiK2krXCJdXCJcbiAgICB0U3RyaWRlW2ldID0gXCJiW2lcIitpK1wiXVwiXG4gIH1cbiAgY29kZS5wdXNoKFwicHJvdG8udHJhbnNwb3NlPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl90cmFuc3Bvc2UoXCIrYXJncytcIil7XCIrXG4gICAgYXJncy5tYXAoZnVuY3Rpb24obixpZHgpIHsgcmV0dXJuIG4gKyBcIj0oXCIgKyBuICsgXCI9PT11bmRlZmluZWQ/XCIgKyBpZHggKyBcIjpcIiArIG4gKyBcInwwKVwifSkuam9pbihcIjtcIiksXG4gICAgXCJ2YXIgYT10aGlzLnNoYXBlLGI9dGhpcy5zdHJpZGU7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLFwiK3RTaGFwZS5qb2luKFwiLFwiKStcIixcIit0U3RyaWRlLmpvaW4oXCIsXCIpK1wiLHRoaXMub2Zmc2V0KX1cIilcblxuICAvL3ZpZXcucGljaygpOlxuICBjb2RlLnB1c2goXCJwcm90by5waWNrPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9waWNrKFwiK2FyZ3MrXCIpe3ZhciBhPVtdLGI9W10sYz10aGlzLm9mZnNldFwiKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcImlmKHR5cGVvZiBpXCIraStcIj09PSdudW1iZXInJiZpXCIraStcIj49MCl7Yz0oYyt0aGlzLnN0cmlkZVtcIitpK1wiXSppXCIraStcIil8MH1lbHNle2EucHVzaCh0aGlzLnNoYXBlW1wiK2krXCJdKTtiLnB1c2godGhpcy5zdHJpZGVbXCIraStcIl0pfVwiKVxuICB9XG4gIGNvZGUucHVzaChcInZhciBjdG9yPUNUT1JfTElTVFthLmxlbmd0aCsxXTtyZXR1cm4gY3Rvcih0aGlzLmRhdGEsYSxiLGMpfVwiKVxuXG4gIC8vQWRkIHJldHVybiBzdGF0ZW1lbnRcbiAgY29kZS5wdXNoKFwicmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF9cIitjbGFzc05hbWUrXCIoZGF0YSxzaGFwZSxzdHJpZGUsb2Zmc2V0KXtyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIihkYXRhLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcInNoYXBlW1wiK2krXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJzdHJpZGVbXCIraStcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLG9mZnNldCl9XCIpXG5cbiAgLy9Db21waWxlIHByb2NlZHVyZVxuICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKFwiQ1RPUl9MSVNUXCIsIFwiT1JERVJcIiwgY29kZS5qb2luKFwiXFxuXCIpKVxuICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdLCBvcmRlcilcbn1cblxuZnVuY3Rpb24gYXJyYXlEVHlwZShkYXRhKSB7XG4gIGlmKGlzQnVmZmVyKGRhdGEpKSB7XG4gICAgcmV0dXJuIFwiYnVmZmVyXCJcbiAgfVxuICBpZihoYXNUeXBlZEFycmF5cykge1xuICAgIHN3aXRjaChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0YSkpIHtcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEZsb2F0NjRBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiZmxvYXQ2NFwiXG4gICAgICBjYXNlIFwiW29iamVjdCBGbG9hdDMyQXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImZsb2F0MzJcIlxuICAgICAgY2FzZSBcIltvYmplY3QgSW50OEFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJpbnQ4XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEludDE2QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImludDE2XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEludDMyQXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImludDMyXCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IFVpbnQ4QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcInVpbnQ4XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IFVpbnQxNkFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJ1aW50MTZcIlxuICAgICAgY2FzZSBcIltvYmplY3QgVWludDMyQXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcInVpbnQzMlwiXG4gICAgICBjYXNlIFwiW29iamVjdCBVaW50OENsYW1wZWRBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwidWludDhfY2xhbXBlZFwiXG4gICAgfVxuICB9XG4gIGlmKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICByZXR1cm4gXCJhcnJheVwiXG4gIH1cbiAgcmV0dXJuIFwiZ2VuZXJpY1wiXG59XG5cbnZhciBDQUNIRURfQ09OU1RSVUNUT1JTID0ge1xuICBcImZsb2F0MzJcIjpbXSxcbiAgXCJmbG9hdDY0XCI6W10sXG4gIFwiaW50OFwiOltdLFxuICBcImludDE2XCI6W10sXG4gIFwiaW50MzJcIjpbXSxcbiAgXCJ1aW50OFwiOltdLFxuICBcInVpbnQxNlwiOltdLFxuICBcInVpbnQzMlwiOltdLFxuICBcImFycmF5XCI6W10sXG4gIFwidWludDhfY2xhbXBlZFwiOltdLFxuICBcImJ1ZmZlclwiOltdLFxuICBcImdlbmVyaWNcIjpbXVxufVxuXG47KGZ1bmN0aW9uKCkge1xuICBmb3IodmFyIGlkIGluIENBQ0hFRF9DT05TVFJVQ1RPUlMpIHtcbiAgICBDQUNIRURfQ09OU1RSVUNUT1JTW2lkXS5wdXNoKGNvbXBpbGVDb25zdHJ1Y3RvcihpZCwgLTEpKVxuICB9XG59KTtcblxuZnVuY3Rpb24gd3JhcHBlZE5EQXJyYXlDdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkge1xuICBpZihkYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICB2YXIgY3RvciA9IENBQ0hFRF9DT05TVFJVQ1RPUlMuYXJyYXlbMF1cbiAgICByZXR1cm4gY3RvcihbXSlcbiAgfSBlbHNlIGlmKHR5cGVvZiBkYXRhID09PSBcIm51bWJlclwiKSB7XG4gICAgZGF0YSA9IFtkYXRhXVxuICB9XG4gIGlmKHNoYXBlID09PSB1bmRlZmluZWQpIHtcbiAgICBzaGFwZSA9IFsgZGF0YS5sZW5ndGggXVxuICB9XG4gIHZhciBkID0gc2hhcGUubGVuZ3RoXG4gIGlmKHN0cmlkZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgc3RyaWRlID0gbmV3IEFycmF5KGQpXG4gICAgZm9yKHZhciBpPWQtMSwgc3o9MTsgaT49MDsgLS1pKSB7XG4gICAgICBzdHJpZGVbaV0gPSBzelxuICAgICAgc3ogKj0gc2hhcGVbaV1cbiAgICB9XG4gIH1cbiAgaWYob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICBvZmZzZXQgPSAwXG4gICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgICBpZihzdHJpZGVbaV0gPCAwKSB7XG4gICAgICAgIG9mZnNldCAtPSAoc2hhcGVbaV0tMSkqc3RyaWRlW2ldXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHZhciBkdHlwZSA9IGFycmF5RFR5cGUoZGF0YSlcbiAgdmFyIGN0b3JfbGlzdCA9IENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdXG4gIHdoaWxlKGN0b3JfbGlzdC5sZW5ndGggPD0gZCsxKSB7XG4gICAgY3Rvcl9saXN0LnB1c2goY29tcGlsZUNvbnN0cnVjdG9yKGR0eXBlLCBjdG9yX2xpc3QubGVuZ3RoLTEpKVxuICB9XG4gIHZhciBjdG9yID0gY3Rvcl9saXN0W2QrMV1cbiAgcmV0dXJuIGN0b3IoZGF0YSwgc2hhcGUsIHN0cmlkZSwgb2Zmc2V0KVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHdyYXBwZWROREFycmF5Q3RvclxuIl19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/wisp/terrain3.js	Sat Jun 25 15:57:05 2016 +0000
@@ -0,0 +1,571 @@
+{
+    var _ns_ = {
+        id: 'demo',
+        doc: void 0
+    };
+    var ndarray = require('ndarray');
+}
+var width = exports.width = 610;
+var height = exports.height = 400;
+var wireframe = exports.wireframe = true;
+var wireframeWidth = exports.wireframeWidth = 1.2;
+var terrainHeight = exports.terrainHeight = 50;
+var terrainSize = exports.terrainSize = 100;
+void 0;
+void 0;
+void 0;
+var inc = exports.inc = function inc(x) {
+    return x + 1;
+};
+var dec = exports.dec = function dec(x) {
+    return x - 1;
+};
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+void 0;
+var midpoint = exports.midpoint = function midpoint(a, b) {
+    return (a + b) / 2;
+};
+var average2 = exports.average2 = function average2(a, b) {
+    return (a + b) / 2;
+};
+var average4 = exports.average4 = function average4(a, b, c, d) {
+    return (a + b + c + d) / 4;
+};
+var safeAverage = exports.safeAverage = function safeAverage(a, b, c, d) {
+    return function () {
+        var totalø1 = 0;
+        var countø1 = 0;
+        a ? (function () {
+            totalø1 = totalø1 + a;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        b ? (function () {
+            totalø1 = totalø1 + b;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        c ? (function () {
+            totalø1 = totalø1 + c;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        d ? (function () {
+            totalø1 = totalø1 + d;
+            return countø1 = inc(countø1);
+        })() : void 0;
+        return totalø1 / countø1;
+    }.call(this);
+};
+var isEven = exports.isEven = function isEven(n) {
+    return 0 == n % 2;
+};
+var isOdd = exports.isOdd = function isOdd(n) {
+    return 1 == n % 2;
+};
+var rand = exports.rand = function rand() {
+    return Math.random();
+};
+var randAroundZero = exports.randAroundZero = function randAroundZero(spread) {
+    return spread * rand() * 2 - spread;
+};
+var jitter = exports.jitter = function jitter(value, spread) {
+    return value + randAroundZero(spread);
+};
+var heightmapResolution = exports.heightmapResolution = function heightmapResolution(heightmap) {
+    return heightmap.shape[0];
+};
+var heightmapLastIndex = exports.heightmapLastIndex = function heightmapLastIndex(heightmap) {
+    return dec(heightmapResolution(heightmap));
+};
+var heightmapCenterIndex = exports.heightmapCenterIndex = function heightmapCenterIndex(heightmap) {
+    return midpoint(0, heightmapLastIndex(heightmap));
+};
+var heightmapGet = exports.heightmapGet = function heightmapGet(heightmap, x, y) {
+    return heightmap.get(x, y);
+};
+var heightmapGetSafe = exports.heightmapGetSafe = function heightmapGetSafe(heightmap, x, y) {
+    return function () {
+        var lastø1 = heightmapLastIndex(heightmap);
+        return 0 <= x && x <= lastø1 && (0 <= y && y <= lastø1) ? (function () {
+            return heightmapGet(heightmap, x, y);
+        })() : void 0;
+    }.call(this);
+};
+var heightmapSet = exports.heightmapSet = function heightmapSet(heightmap, x, y, val) {
+    return heightmap.set(x, y, val);
+};
+var heightmapSetIfUnset = exports.heightmapSetIfUnset = function heightmapSetIfUnset(heightmap, x, y, val) {
+    return 0 == heightmapGet(heightmap, x, y) ? (function () {
+        return heightmapSet(heightmap, x, y, val);
+    })() : void 0;
+};
+var normalize = exports.normalize = function normalize(heightmap) {
+    return function () {
+        var maxø1 = 0 - Infinity;
+        var minø1 = Infinity;
+        (function () {
+            var array2ø1 = heightmap;
+            return function () {
+                var G__3ø1 = array2ø1.data.length;
+                return function loop() {
+                    var recur = loop;
+                    var index1ø1 = 0;
+                    do {
+                        recur = index1ø1 < G__3ø1 ? (function () {
+                            (function () {
+                                var elø1 = array2ø1.data[index1ø1];
+                                maxø1 < elø1 ? (function () {
+                                    return maxø1 = elø1;
+                                })() : void 0;
+                                return minø1 > elø1 ? (function () {
+                                    return minø1 = elø1;
+                                })() : void 0;
+                            }.call(this));
+                            return loop[0] = inc(index1ø1), loop;
+                        })() : void 0;
+                    } while (index1ø1 = loop[0], recur === loop);
+                    return recur;
+                }.call(this);
+            }.call(this);
+        }.call(this));
+        return function () {
+            var spanø1 = maxø1 - minø1;
+            return function () {
+                var array4ø1 = heightmap;
+                return function () {
+                    var G__5ø1 = array4ø1.shape[0];
+                    return function loop() {
+                        var recur = loop;
+                        var xø1 = 0;
+                        do {
+                            recur = xø1 < G__5ø1 ? (function () {
+                                (function () {
+                                    var G__6ø1 = array4ø1.shape[1];
+                                    return function loop() {
+                                        var recur = loop;
+                                        var yø1 = 0;
+                                        do {
+                                            recur = yø1 < G__6ø1 ? (function () {
+                                                (function () {
+                                                    return heightmapSet(heightmap, xø1, yø1, (heightmapGet(heightmap, xø1, yø1) - minø1) / spanø1);
+                                                })();
+                                                return loop[0] = inc(yø1), loop;
+                                            })() : void 0;
+                                        } while (yø1 = loop[0], recur === loop);
+                                        return recur;
+                                    }.call(this);
+                                }.call(this));
+                                return loop[0] = inc(xø1), loop;
+                            })() : void 0;
+                        } while (xø1 = loop[0], recur === loop);
+                        return recur;
+                    }.call(this);
+                }.call(this);
+            }.call(this);
+        }.call(this);
+    }.call(this);
+};
+var makeHeightmap = exports.makeHeightmap = function makeHeightmap(exponent) {
+    return function () {
+        var resolutionø1 = Math.pow(2, exponent) + 1;
+        return function () {
+            var heightmapø1 = ndarray(new Float64Array(resolutionø1 * resolutionø1), [
+                resolutionø1,
+                resolutionø1
+            ]);
+            heightmapø1.exponent = exponent;
+            heightmapø1.resolution = resolutionø1;
+            heightmapø1.last = dec(resolutionø1);
+            return heightmapø1;
+        }.call(this);
+    }.call(this);
+};
+var topLeftCorner = exports.topLeftCorner = function topLeftCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(0, 0).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var topRightCorner = exports.topRightCorner = function topRightCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(centerø1, 0).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var bottomLeftCorner = exports.bottomLeftCorner = function bottomLeftCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(0, centerø1).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var bottomRightCorner = exports.bottomRightCorner = function bottomRightCorner(heightmap) {
+    return function () {
+        var centerø1 = heightmapCenterIndex(heightmap);
+        return heightmap.lo(centerø1, centerø1).hi(inc(centerø1), inc(centerø1));
+    }.call(this);
+};
+var dsInitCorners = exports.dsInitCorners = function dsInitCorners(heightmap) {
+    return function () {
+        var lastø1 = heightmapLastIndex(heightmap);
+        heightmapSet(heightmap, 0, 0, rand());
+        heightmapSet(heightmap, 0, lastø1, rand());
+        heightmapSet(heightmap, lastø1, 0, rand());
+        return heightmapSet(heightmap, lastø1, lastø1, rand());
+    }.call(this);
+};
+var dsSquare = exports.dsSquare = function dsSquare(heightmap, x, y, radius, spread) {
+    return function () {
+        var newHeightø1 = jitter(average4(heightmapGet(heightmap, x - radius, y - radius), heightmapGet(heightmap, x - radius, y + radius), heightmapGet(heightmap, x + radius, y - radius), heightmapGet(heightmap, x + radius, y + radius)), spread);
+        return heightmapSet(heightmap, x, y, newHeightø1);
+    }.call(this);
+};
+var dsDiamond = exports.dsDiamond = function dsDiamond(heightmap, x, y, radius, spread) {
+    return function () {
+        var newHeightø1 = jitter(safeAverage(heightmapGetSafe(heightmap, x - radius, y), heightmapGetSafe(heightmap, x + radius, y), heightmapGetSafe(heightmap, x, y - radius), heightmapGetSafe(heightmap, x, y + radius)), spread);
+        return heightmapSet(heightmap, x, y, newHeightø1);
+    }.call(this);
+};
+var dsSquares = exports.dsSquares = function dsSquares(heightmap, radius, spread) {
+    return function () {
+        var start8ø1 = radius;
+        var end9ø1 = heightmapResolution(heightmap);
+        var stride7ø1 = 2 * radius;
+        return function loop() {
+            var recur = loop;
+            var xø1 = start8ø1;
+            do {
+                recur = xø1 < end9ø1 ? (function () {
+                    (function loop() {
+                        var recur = loop;
+                        var yø1 = start8ø1;
+                        do {
+                            recur = yø1 < end9ø1 ? (function () {
+                                (function () {
+                                    return dsSquare(heightmap, xø1, yø1, radius, spread);
+                                })();
+                                return loop[0] = yø1 + stride7ø1, loop;
+                            })() : void 0;
+                        } while (yø1 = loop[0], recur === loop);
+                        return recur;
+                    }.call(this));
+                    return loop[0] = xø1 + stride7ø1, loop;
+                })() : void 0;
+            } while (xø1 = loop[0], recur === loop);
+            return recur;
+        }.call(this);
+    }.call(this);
+};
+var dsDiamonds = exports.dsDiamonds = function dsDiamonds(heightmap, radius, spread) {
+    return function () {
+        var sizeø1 = heightmapResolution(heightmap);
+        return function () {
+            var start11ø1 = 0;
+            var end12ø1 = sizeø1;
+            var stride10ø1 = radius;
+            return function loop() {
+                var recur = loop;
+                var yø1 = start11ø1;
+                do {
+                    recur = yø1 < end12ø1 ? (function () {
+                        (function () {
+                            return function () {
+                                var shiftø1 = isEven(yø1 / radius) ? radius : 0;
+                                return function () {
+                                    var start14ø1 = shiftø1;
+                                    var end15ø1 = sizeø1;
+                                    var stride13ø1 = 2 * radius;
+                                    return function loop() {
+                                        var recur = loop;
+                                        var xø1 = start14ø1;
+                                        do {
+                                            recur = xø1 < end15ø1 ? (function () {
+                                                (function () {
+                                                    return dsDiamond(heightmap, xø1, yø1, radius, spread);
+                                                })();
+                                                return loop[0] = xø1 + stride13ø1, loop;
+                                            })() : void 0;
+                                        } while (xø1 = loop[0], recur === loop);
+                                        return recur;
+                                    }.call(this);
+                                }.call(this);
+                            }.call(this);
+                        })();
+                        return loop[0] = yø1 + stride10ø1, loop;
+                    })() : void 0;
+                } while (yø1 = loop[0], recur === loop);
+                return recur;
+            }.call(this);
+        }.call(this);
+    }.call(this);
+};
+var diamondSquare = exports.diamondSquare = function diamondSquare(heightmap) {
+    return function () {
+        var initialSpreadø1 = 0.3;
+        var spreadReductionø1 = 0.5;
+        var centerø1 = heightmapCenterIndex(heightmap);
+        var sizeø1 = heightmap.shape[0];
+        dsInitCorners(heightmap);
+        (function loop() {
+            var recur = loop;
+            var radiusø1 = centerø1;
+            var spreadø1 = initialSpreadø1;
+            do {
+                recur = radiusø1 >= 1 ? (function () {
+                    dsSquares(heightmap, radiusø1, spreadø1);
+                    dsDiamonds(heightmap, radiusø1, spreadø1);
+                    return loop[0] = radiusø1 / 2, loop[1] = spreadø1 * spreadReductionø1, loop;
+                })() : void 0;
+            } while (radiusø1 = loop[0], spreadø1 = loop[1], recur === loop);
+            return recur;
+        }.call(this));
+        return normalize(heightmap);
+    }.call(this);
+};
+var diamondSquare1 = exports.diamondSquare1 = function diamondSquare1(heightmap) {
+    dsInitCorners(heightmap);
+    return normalize(heightmap);
+};
+var diamondSquare2 = exports.diamondSquare2 = function diamondSquare2(heightmap) {
+    return function () {
+        var initialSpreadø1 = 0.3;
+        var spreadReductionø1 = 0.5;
+        var centerø1 = heightmapCenterIndex(heightmap);
+        var sizeø1 = heightmap.shape[0];
+        dsInitCorners(heightmap);
+        dsSquares(heightmap, centerø1, initialSpreadø1);
+        return normalize(heightmap);
+    }.call(this);
+};
+var diamondSquare3 = exports.diamondSquare3 = function diamondSquare3(heightmap) {
+    return function () {
+        var initialSpreadø1 = 0.3;
+        var spreadReductionø1 = 0.5;
+        var centerø1 = heightmapCenterIndex(heightmap);
+        var sizeø1 = heightmap.shape[0];
+        dsInitCorners(heightmap);
+        dsSquares(heightmap, centerø1, initialSpreadø1);
+        dsDiamonds(heightmap, centerø1, initialSpreadø1);
+        dsSquares(heightmap, centerø1 / 2, spreadReductionø1 * initialSpreadø1);
+        dsDiamonds(heightmap, centerø1 / 2, spreadReductionø1 * initialSpreadø1);
+        return normalize(heightmap);
+    }.call(this);
+};
+var makeDirectionalLight = exports.makeDirectionalLight = function makeDirectionalLight() {
+    return function () {
+        var lightø1 = new THREE.DirectionalLight(16777215, 1);
+        lightø1.position.set(100, 0, 150);
+        return lightø1;
+    }.call(this);
+};
+var makeCamera = exports.makeCamera = function makeCamera() {
+    return function () {
+        var cameraø1 = new THREE.PerspectiveCamera(55, width / height, 0.1, 1000);
+        cameraø1.position.set(0, -100, 150);
+        return cameraø1;
+    }.call(this);
+};
+var makeRenderer = exports.makeRenderer = function makeRenderer() {
+    return function () {
+        var rendererø1 = new THREE.WebGLRenderer({ 'antialias': false });
+        rendererø1.setClearColor(16777215);
+        rendererø1.setSize(width, height);
+        rendererø1.setPixelRatio(2);
+        return rendererø1;
+    }.call(this);
+};
+var makeGeometry = exports.makeGeometry = function makeGeometry(heightmap) {
+    return function () {
+        var resolutionø1 = heightmap.shape[0];
+        var geometryø1 = new THREE.PlaneGeometry(terrainSize, terrainSize, resolutionø1 - 1, resolutionø1 - 1);
+        return geometryø1;
+    }.call(this);
+};
+var makeControls = exports.makeControls = function makeControls(camera, renderer) {
+    return function () {
+        var controlsø1 = new THREE.TrackballControls(camera, renderer.domElement);
+        controlsø1.rotateSpeed = 1.4;
+        controlsø1.zoomSpeed = 0.5;
+        controlsø1.staticMoving = true;
+        controlsø1.dynamicDampingFactor = 0.3;
+        return controlsø1;
+    }.call(this);
+};
+var makePlane = exports.makePlane = function makePlane(geometry) {
+    return function () {
+        var materialø1 = new THREE.MeshLambertMaterial({
+            'wireframe': wireframe,
+            'wireframeLinewidth': wireframeWidth,
+            'color': 47872
+        });
+        return new THREE.Mesh(geometry, materialø1);
+    }.call(this);
+};
+var attachToDom = exports.attachToDom = function attachToDom(renderer, elName, refreshFn) {
+    return function () {
+        var containerø1 = document.getElementById(elName);
+        var settingsø1 = document.createElement('div');
+        var refreshButtonø1 = document.createElement('button');
+        var buttonTextø1 = document.createTextNode('Refresh');
+        var cancelScrollø1 = function (e) {
+            return e.preventDefault();
+        };
+        refreshButtonø1.onclick = refreshFn;
+        renderer.domElement.onmousewheel = cancelScrollø1;
+        renderer.domElement.addEventListener('MozMousePixelScroll', cancelScrollø1, false);
+        refreshButtonø1.appendChild(buttonTextø1);
+        containerø1.appendChild(renderer.domElement);
+        containerø1.appendChild(settingsø1);
+        return settingsø1.appendChild(refreshButtonø1);
+    }.call(this);
+};
+var updateGeometry = exports.updateGeometry = function updateGeometry(geometry, heightmap) {
+    (function loop() {
+        var recur = loop;
+        var iø1 = 0;
+        do {
+            recur = iø1 < geometry.vertices.length ? (function () {
+                geometry.vertices[iø1].z = terrainHeight * heightmap.data[iø1];
+                return loop[0] = iø1 + 1, loop;
+            })() : void 0;
+        } while (iø1 = loop[0], recur === loop);
+        return recur;
+    }.call(this));
+    geometry.computeVertexNormals();
+    return geometry;
+};
+var makeDemo = exports.makeDemo = function makeDemo(elementId, algorithm, size) {
+    var scene = new THREE.Scene();
+    scene.add(new THREE.AxisHelper(100));
+    var clock = new THREE.Clock();
+    var camera = makeCamera();
+    var renderer = makeRenderer();
+    var geometry = void 0;
+    var plane = void 0;
+    scene.add(makeDirectionalLight());
+    scene.add(new THREE.AmbientLight(16777215, 0.05));
+    var refresh = function refresh() {
+        return function () {
+            var heightmapø1 = makeHeightmap(size);
+            console.log('Generating terrain...');
+            (function () {
+                var G__16ø1 = new Date().getTime();
+                var G__18ø1 = (function () {
+                    return algorithm(heightmapø1);
+                })();
+                var G__17ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__17ø1 - G__16ø1) + 'ms.');
+                return G__18ø1;
+            }.call(this));
+            console.log('Rebuilding geometry...');
+            (function () {
+                var G__19ø1 = new Date().getTime();
+                var G__21ø1 = (function () {
+                    geometry = makeGeometry(heightmapø1);
+                    return updateGeometry(geometry, heightmapø1);
+                })();
+                var G__20ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__20ø1 - G__19ø1) + 'ms.');
+                return G__21ø1;
+            }.call(this));
+            console.log('Rebuilding plane...');
+            return function () {
+                var G__22ø1 = new Date().getTime();
+                var G__24ø1 = (function () {
+                    scene.remove(plane);
+                    plane = makePlane(geometry);
+                    return scene.add(plane);
+                })();
+                var G__23ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__23ø1 - G__22ø1) + 'ms.');
+                return G__24ø1;
+            }.call(this);
+        }.call(this);
+    };
+    attachToDom(renderer, elementId, refresh);
+    var controls = makeControls(camera, renderer);
+    var render = function render() {
+        return function () {
+            var deltaø1 = clock.getDelta();
+            requestAnimationFrame(render);
+            controls.update(deltaø1);
+            return renderer.render(scene, camera);
+        }.call(this);
+    };
+    refresh();
+    render();
+    return void 0;
+};
+var makeFinal = exports.makeFinal = function makeFinal(elementId) {
+    var scene = new THREE.Scene();
+    scene.add(new THREE.AxisHelper(100));
+    var clock = new THREE.Clock();
+    var camera = makeCamera();
+    var renderer = makeRenderer();
+    var geometry = void 0;
+    var plane = void 0;
+    scene.add(makeDirectionalLight());
+    scene.add(new THREE.AmbientLight(16777215, 0.05));
+    var refresh = function refresh() {
+        return function () {
+            var heightmapø1 = makeHeightmap(6);
+            console.log('Generating terrain...');
+            (function () {
+                var G__25ø1 = new Date().getTime();
+                var G__27ø1 = (function () {
+                    return diamondSquare(heightmapø1);
+                })();
+                var G__26ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__26ø1 - G__25ø1) + 'ms.');
+                return G__27ø1;
+            }.call(this));
+            console.log('Rebuilding geometry...');
+            (function () {
+                var G__28ø1 = new Date().getTime();
+                var G__30ø1 = (function () {
+                    geometry = makeGeometry(heightmapø1);
+                    return updateGeometry(geometry, heightmapø1);
+                })();
+                var G__29ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__29ø1 - G__28ø1) + 'ms.');
+                return G__30ø1;
+            }.call(this));
+            console.log('Rebuilding plane...');
+            return function () {
+                var G__31ø1 = new Date().getTime();
+                var G__33ø1 = (function () {
+                    scene.remove(plane);
+                    plane = makePlane(geometry);
+                    return scene.add(plane);
+                })();
+                var G__32ø1 = new Date().getTime();
+                console.log('Elapsed time: ' + (G__32ø1 - G__31ø1) + 'ms.');
+                return G__33ø1;
+            }.call(this);
+        }.call(this);
+    };
+    attachToDom(renderer, elementId, refresh);
+    var controls = makeControls(camera, renderer);
+    var render = function render() {
+        return function () {
+            var deltaø1 = clock.getDelta();
+            requestAnimationFrame(render);
+            controls.update(deltaø1);
+            return renderer.render(scene, camera);
+        }.call(this);
+    };
+    refresh();
+    render();
+    return void 0;
+};
+var run = exports.run = function run() {
+    makeDemo('demo-1', diamondSquare1, 2);
+    makeDemo('demo-2', diamondSquare2, 4);
+    makeDemo('demo-3', diamondSquare3, 4);
+    return makeFinal('demo-final');
+};
+$(run);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImFub255bW91cy53aXNwIl0sIm5hbWVzIjpbIl9uc18iLCJpZCIsImRvYyIsIndpZHRoIiwiZXhwb3J0cyIsImhlaWdodCIsIndpcmVmcmFtZSIsIndpcmVmcmFtZVdpZHRoIiwidGVycmFpbkhlaWdodCIsInRlcnJhaW5TaXplIiwiaW5jIiwieCIsImRlYyIsIm1pZHBvaW50IiwiYSIsImIiLCJhdmVyYWdlMiIsImF2ZXJhZ2U0IiwiYyIsImQiLCJzYWZlQXZlcmFnZSIsInRvdGFsw7gxIiwiY291bnTDuDEiLCJpc0V2ZW4iLCJuIiwiaXNPZGQiLCJyYW5kIiwiTWF0aCIsInJhbmRvbSIsInJhbmRBcm91bmRaZXJvIiwic3ByZWFkIiwiaml0dGVyIiwidmFsdWUiLCJoZWlnaHRtYXBSZXNvbHV0aW9uIiwiaGVpZ2h0bWFwIiwic2hhcGUiLCJoZWlnaHRtYXBMYXN0SW5kZXgiLCJoZWlnaHRtYXBDZW50ZXJJbmRleCIsImhlaWdodG1hcEdldCIsInkiLCJnZXQiLCJoZWlnaHRtYXBHZXRTYWZlIiwibGFzdMO4MSIsImhlaWdodG1hcFNldCIsInZhbCIsInNldCIsImhlaWdodG1hcFNldElmVW5zZXQiLCJub3JtYWxpemUiLCJtYXjDuDEiLCJJbmZpbml0eSIsIm1pbsO4MSIsImVsw7gxIiwic3BhbsO4MSIsInjDuDEiLCJ5w7gxIiwibWFrZUhlaWdodG1hcCIsImV4cG9uZW50IiwicmVzb2x1dGlvbsO4MSIsInBvdyIsImhlaWdodG1hcMO4MSIsIm5kYXJyYXkiLCJGbG9hdDY0QXJyYXkiLCJyZXNvbHV0aW9uIiwibGFzdCIsInRvcExlZnRDb3JuZXIiLCJjZW50ZXLDuDEiLCJsbyIsImhpIiwidG9wUmlnaHRDb3JuZXIiLCJib3R0b21MZWZ0Q29ybmVyIiwiYm90dG9tUmlnaHRDb3JuZXIiLCJkc0luaXRDb3JuZXJzIiwiZHNTcXVhcmUiLCJyYWRpdXMiLCJuZXdIZWlnaHTDuDEiLCJkc0RpYW1vbmQiLCJkc1NxdWFyZXMiLCJkc0RpYW1vbmRzIiwic2l6ZcO4MSIsInNoaWZ0w7gxIiwiZGlhbW9uZFNxdWFyZSIsImluaXRpYWxTcHJlYWTDuDEiLCJzcHJlYWRSZWR1Y3Rpb27DuDEiLCJyYWRpdXPDuDEiLCJzcHJlYWTDuDEiLCJkaWFtb25kU3F1YXJlMSIsImRpYW1vbmRTcXVhcmUyIiwiZGlhbW9uZFNxdWFyZTMiLCJtYWtlRGlyZWN0aW9uYWxMaWdodCIsImxpZ2h0w7gxIiwiVEhSRUUiLCJEaXJlY3Rpb25hbExpZ2h0IiwicG9zaXRpb24uc2V0IiwibWFrZUNhbWVyYSIsImNhbWVyYcO4MSIsIlBlcnNwZWN0aXZlQ2FtZXJhIiwibWFrZVJlbmRlcmVyIiwicmVuZGVyZXLDuDEiLCJXZWJHTFJlbmRlcmVyIiwic2V0Q2xlYXJDb2xvciIsInNldFNpemUiLCJzZXRQaXhlbFJhdGlvIiwibWFrZUdlb21ldHJ5IiwiZ2VvbWV0cnnDuDEiLCJQbGFuZUdlb21ldHJ5IiwibWFrZUNvbnRyb2xzIiwiY2FtZXJhIiwicmVuZGVyZXIiLCJjb250cm9sc8O4MSIsIlRyYWNrYmFsbENvbnRyb2xzIiwiZG9tRWxlbWVudCIsInJvdGF0ZVNwZWVkIiwiem9vbVNwZWVkIiwic3RhdGljTW92aW5nIiwiZHluYW1pY0RhbXBpbmdGYWN0b3IiLCJtYWtlUGxhbmUiLCJnZW9tZXRyeSIsIm1hdGVyaWFsw7gxIiwiTWVzaExhbWJlcnRNYXRlcmlhbCIsIk1lc2giLCJhdHRhY2hUb0RvbSIsImVsTmFtZSIsInJlZnJlc2hGbiIsImNvbnRhaW5lcsO4MSIsImRvY3VtZW50IiwiZ2V0RWxlbWVudEJ5SWQiLCJzZXR0aW5nc8O4MSIsImNyZWF0ZUVsZW1lbnQiLCJyZWZyZXNoQnV0dG9uw7gxIiwiYnV0dG9uVGV4dMO4MSIsImNyZWF0ZVRleHROb2RlIiwiY2FuY2VsU2Nyb2xsw7gxIiwiZSIsInByZXZlbnREZWZhdWx0Iiwib25jbGljayIsImRvbUVsZW1lbnQub25tb3VzZXdoZWVsIiwiZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyIiwiYXBwZW5kQ2hpbGQiLCJ1cGRhdGVHZW9tZXRyeSIsImnDuDEiLCJ2ZXJ0aWNlcy5sZW5ndGgiLCJ2ZXJ0aWNlcyIsInoiLCJkYXRhIiwiY29tcHV0ZVZlcnRleE5vcm1hbHMiLCJtYWtlRGVtbyIsImVsZW1lbnRJZCIsImFsZ29yaXRobSIsInNpemUiLCJzY2VuZSIsIlNjZW5lIiwiYWRkIiwiQXhpc0hlbHBlciIsImNsb2NrIiwiQ2xvY2siLCJwbGFuZSIsIkFtYmllbnRMaWdodCIsInJlZnJlc2giLCJyZW1vdmUiLCJjb250cm9scyIsInJlbmRlciIsImRlbHRhw7gxIiwiZ2V0RGVsdGEiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJ1cGRhdGUiLCJtYWtlRmluYWwiLCJydW4iLCIkIl0sIm1hcHBpbmdzIjoiO0lBQUEsSUFBQ0EsSSxHQUFEO0FBQUEsUUFBQUMsRSxFQUFJLE1BQUo7QUFBQSxRQUFBQyxHLEVBQUEsSyxDQUFBO0FBQUEsTTs7O0FBS0EsSUFBS0MsS0FBQSxHQUFBQyxPQUFBLENBQUFELEtBQUEsR0FBTSxHQUFYLEM7QUFDQSxJQUFLRSxNQUFBLEdBQUFELE9BQUEsQ0FBQUMsTUFBQSxHQUFPLEdBQVosQztBQUNBLElBQUtDLFNBQUEsR0FBQUYsT0FBQSxDQUFBRSxTQUFBLEcsSUFBTCxDO0FBQ0EsSUFBS0MsY0FBQSxHQUFBSCxPQUFBLENBQUFHLGNBQUEsR0FBZ0IsR0FBckIsQztBQUNBLElBQUtDLGFBQUEsR0FBQUosT0FBQSxDQUFBSSxhQUFBLEdBQWUsRUFBcEIsQztBQUNBLElBQUtDLFdBQUEsR0FBQUwsT0FBQSxDQUFBSyxXQUFBLEdBQWEsR0FBbEIsQzs7OztBQW9CQSxJQUFNQyxHQUFBLEdBQUFOLE9BQUEsQ0FBQU0sR0FBQSxHQUFOLFNBQU1BLEdBQU4sQ0FBV0MsQ0FBWCxFQUNFO0FBQUEsV0FBR0EsQ0FBSCxHQUFLLENBQUw7QUFBQSxDQURGLEM7QUFHQSxJQUFNQyxHQUFBLEdBQUFSLE9BQUEsQ0FBQVEsR0FBQSxHQUFOLFNBQU1BLEdBQU4sQ0FBV0QsQ0FBWCxFQUNFO0FBQUEsV0FBR0EsQ0FBSCxH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QUEsSUFFQzJELFFBQUQsQ0FBVyxRQUFYLEVBQW9CMUQsY0FBcEIsRUFBcUMsQ0FBckMsRUFGQTtBQUFBLElBR0EsT0FBQzhFLFNBQUQsQ0FBWSxZQUFaLEVBSEE7QUFBQSxDQURGLEM7QUFNQ0UsQ0FBRCxDQUFHRCxHQUFIIiwic291cmNlc0NvbnRlbnQiOlsiKG5zIGRlbW9cbiAgKDpyZXF1aXJlIFtuZGFycmF5XSkpXG5cblxuOyBDb25zdGFudHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZiB3aWR0aCA2MTApXG4oZGVmIGhlaWdodCA0MDApXG4oZGVmIHdpcmVmcmFtZSB0cnVlKVxuKGRlZiB3aXJlZnJhbWUtd2lkdGggMS4yKVxuKGRlZiB0ZXJyYWluLWhlaWdodCA1MClcbihkZWYgdGVycmFpbi1zaXplIDEwMClcblxuOyBHZW5lcmFsIFV0aWxpdGllcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm1hY3JvIHdoZW4gW2NvbmRpdGlvbiAmIGJvZHldXG4gIGAoaWYgfmNvbmRpdGlvblxuICAgICAoZG8gfkBib2R5KSkpXG5cbihkZWZtYWNybyB3aGVuLW5vdCBbY29uZGl0aW9uICYgYm9keV1cbiAgYCh3aGVuIChub3QgfmNvbmRpdGlvbilcbiAgICAgfkBib2R5KSlcblxuKGRlZm1hY3JvIC0+IFsmIG9wZXJhdGlvbnNdXG4gIChyZWR1Y2VcbiAgICAoZm4gW2Zvcm0gb3BlcmF0aW9uXVxuICAgICAgKGNvbnMgKGZpcnN0IG9wZXJhdGlvbilcbiAgICAgICAgICAgIChjb25zIGZvcm0gKHJlc3Qgb3BlcmF0aW9uKSkpKVxuICAgIChmaXJzdCBvcGVyYXRpb25zKVxuICAgIChyZXN0IG9wZXJhdGlvbnMpKSlcblxuXG4oZGVmbiBpbmMgW3hdXG4gICgrIHggMSkpXG5cbihkZWZuIGRlYyBbeF1cbiAgKC0geCAxKSlcblxuXG4oZGVmbWFjcm8gZG8tdGltZXMgW3Zhcm5hbWUgbGltaXQgJiBib2R5XVxuICAobGV0IFtlbmQgKGdlbnN5bSldXG4gICAgYChsZXQgW35lbmQgfmxpbWl0XVxuICAgICAgIChsb29wIFt+dmFybmFtZSAwXVxuICAgICAgICAgKHdoZW4gKDwgfnZhcm5hbWUgfmVuZClcbiAgICAgICAgICAgfkBib2R5XG4gICAgICAgICAgIChyZWN1ciAoaW5jIH52YXJuYW1lKSkpKSkpKVxuXG4oZGVmbWFjcm8gZG8tc3RyaWRlIFt2YXJuYW1lcyBzdGFydC1mb3JtIGVuZC1mb3JtIHN0cmlkZS1mb3JtICYgYm9keV1cbiAgKGxldCBbc3RyaWRlIChnZW5zeW0gXCJzdHJpZGVcIilcbiAgICAgICAgc3RhcnQgKGdlbnN5bSBcInN0YXJ0XCIpXG4gICAgICAgIGVuZCAoZ2Vuc3ltIFwiZW5kXCIpXG4gICAgICAgIGJ1aWxkIChmbiBidWlsZCBbdmFyc11cbiAgICAgICAgICAgICAgICAoaWYgKGVtcHR5PyB2YXJzKVxuICAgICAgICAgICAgICAgICAgYChkbyB+QGJvZHkpXG4gICAgICAgICAgICAgICAgICAobGV0IFt2YXJuYW1lIChmaXJzdCB2YXJzKV1cbiAgICAgICAgICAgICAgICAgICAgYChsb29wIFt+dmFybmFtZSB+c3RhcnRdXG4gICAgICAgICAgICAgICAgICAgICAgICh3aGVuICg8IH52YXJuYW1lIH5lbmQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgfihidWlsZCAocmVzdCB2YXJzKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAocmVjdXIgKCsgfnZhcm5hbWUgfnN0cmlkZSkpKSkpKSldXG4gICAgOyBGaXggdGhlIG51bWJlcnMgb25jZSBvdXRzaWRlIHRoZSBuZXN0ZWQgbG9vcHMsXG4gICAgOyBhbmQgdGhlbiBidWlsZCB0aGUgZ3V0cy5cbiAgICBgKGxldCBbfnN0YXJ0IH5zdGFydC1mb3JtXG4gICAgICAgICAgIH5lbmQgfmVuZC1mb3JtXG4gICAgICAgICAgIH5zdHJpZGUgfnN0cmlkZS1mb3JtXVxuICAgICAgIH4oYnVpbGQgdmFybmFtZXMpKSkpXG5cblxuKGRlZm1hY3JvIGRvLW5kYXJyYXkgW3ZhcnMgYXJyYXktZm9ybSAmIGJvZHldXG4gIChsZXQgW2FycmF5LXZhciAoZ2Vuc3ltIFwiYXJyYXlcIilcbiAgICAgICAgYnVpbGQgKGZuIGJ1aWxkIFt2YXJzIG5dXG4gICAgICAgICAgICAgICAgKGlmIChlbXB0eT8gdmFycylcbiAgICAgICAgICAgICAgICAgIGAoZG8gfkBib2R5KVxuICAgICAgICAgICAgICAgICAgYChkby10aW1lcyB+KGZpcnN0IHZhcnMpIChhZ2V0ICguLXNoYXBlIH5hcnJheS12YXIpIH5uKVxuICAgICAgICAgICAgICAgICAgICAgfihidWlsZCAocmVzdCB2YXJzKSAoaW5jIG4pKSkpKV1cbiAgICBgKGxldCBbfmFycmF5LXZhciB+YXJyYXktZm9ybV1cbiAgICAgICB+KGJ1aWxkIHZhcnMgMCkpKSlcblxuKGRlZm1hY3JvIGRvLW5kYXJyYXktZWwgW2VsZW1lbnQgYXJyYXktZm9ybSAmIGJvZHldXG4gIChsZXQgW2luZGV4IChnZW5zeW0gXCJpbmRleFwiKVxuICAgICAgICBhcnJheSAoZ2Vuc3ltIFwiYXJyYXlcIildXG4gICAgYChsZXQgW35hcnJheSB+YXJyYXktZm9ybV1cbiAgICAgICAoZG8tdGltZXMgfmluZGV4ICguLWxlbmd0aCAoLi1kYXRhIH5hcnJheSkpXG4gICAgICAgICAobGV0IFt+ZWxlbWVudCAoYWdldCAoLi1kYXRhIH5hcnJheSkgfmluZGV4KV1cbiAgICAgICAgICAgfkBib2R5KSkpKSlcblxuXG4oZGVmbWFjcm8gaW5jISBbcGxhY2VdXG4gIGAoc2V0ISB+cGxhY2UgKGluYyB+cGxhY2UpKSlcblxuKGRlZm1hY3JvIGFkZCEgW3BsYWNlIGFtb3VudF1cbiAgYChzZXQhIH5wbGFjZSAoKyB+cGxhY2UgfmFtb3VudCkpKVxuXG5cbihkZWZtYWNybyBsIFsmIGZvcm1zXVxuICBgKGNvbnNvbGUubG9nIH5AZm9ybXMpKVxuXG4oZGVmbWFjcm8gdGltZSBbJiBib2R5XVxuICAobGV0IFtzdGFydCAoZ2Vuc3ltKVxuICAgICAgICBlbmQgKGdlbnN5bSlcbiAgICAgICAgcmVzdWx0IChnZW5zeW0pXVxuICAgIGAobGV0IFt+c3RhcnQgKC5nZXRUaW1lIChuZXcgRGF0ZSkpXG4gICAgICAgICAgIH5yZXN1bHQgKGRvIH5AYm9keSlcbiAgICAgICAgICAgfmVuZCAoLmdldFRpbWUgKG5ldyBEYXRlKSldXG4gICAgICAgKGwgKCsgXCJFbGFwc2VkIHRpbWU6IFwiICgtIH5lbmQgfnN0YXJ0KSBcIm1zLlwiKSlcbiAgICAgICB+cmVzdWx0KSkpXG5cblxuKGRlZm4gbWlkcG9pbnQgW2EgYl1cbiAgKC8gKCsgYSBiKSAyKSlcblxuKGRlZm4gYXZlcmFnZTIgW2EgYl1cbiAgKC8gKCsgYSBiKSAyKSlcblxuKGRlZm4gYXZlcmFnZTQgW2EgYiBjIGRdXG4gICgvICgrIGEgYiBjIGQpIDQpKVxuXG4oZGVmbiBzYWZlLWF2ZXJhZ2UgW2EgYiBjIGRdXG4gIChsZXQgW3RvdGFsIDAgY291bnQgMF1cbiAgICAod2hlbiBhIChhZGQhIHRvdGFsIGEpIChpbmMhIGNvdW50KSlcbiAgICAod2hlbiBiIChhZGQhIHRvdGFsIGIpIChpbmMhIGNvdW50KSlcbiAgICAod2hlbiBjIChhZGQhIHRvdGFsIGMpIChpbmMhIGNvdW50KSlcbiAgICAod2hlbiBkIChhZGQhIHRvdGFsIGQpIChpbmMhIGNvdW50KSlcbiAgICAoLyB0b3RhbCBjb3VudCkpKVxuXG5cbihkZWZuIGV2ZW4/IFtuXVxuICAoPT0gMCAobW9kIG4gMikpKVxuXG4oZGVmbiBvZGQ/IFtuXVxuICAoPT0gMSAobW9kIG4gMikpKVxuXG5cbjsgUmFuZG9tbmVzcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIHJhbmQgW11cbiAgKE1hdGgucmFuZG9tKSlcblxuKGRlZm4gcmFuZC1hcm91bmQtemVybyBbc3ByZWFkXVxuICAoLSAoKiBzcHJlYWQgKHJhbmQpIDIpIHNwcmVhZCkpXG5cbihkZWZuIGppdHRlciBbdmFsdWUgc3ByZWFkXVxuICAoKyB2YWx1ZSAocmFuZC1hcm91bmQtemVybyBzcHJlYWQpKSlcblxuXG47IEhlaWdodG1hcCBIZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbiBoZWlnaHRtYXAtcmVzb2x1dGlvbiBbaGVpZ2h0bWFwXVxuICAoYWdldCBoZWlnaHRtYXAuc2hhcGUgMCkpXG5cbihkZWZuIGhlaWdodG1hcC1sYXN0LWluZGV4IFtoZWlnaHRtYXBdXG4gIChkZWMgKGhlaWdodG1hcC1yZXNvbHV0aW9uIGhlaWdodG1hcCkpKVxuXG4oZGVmbiBoZWlnaHRtYXAtY2VudGVyLWluZGV4IFtoZWlnaHRtYXBdXG4gIChtaWRwb2ludCAwIChoZWlnaHRtYXAtbGFzdC1pbmRleCBoZWlnaHRtYXApKSlcblxuXG4oZGVmbiBoZWlnaHRtYXAtZ2V0IFtoZWlnaHRtYXAgeCB5XVxuICAoLmdldCBoZWlnaHRtYXAgeCB5KSlcblxuKGRlZm4gaGVpZ2h0bWFwLWdldC1zYWZlIFtoZWlnaHRtYXAgeCB5XVxuICAobGV0IFtsYXN0IChoZWlnaHRtYXAtbGFzdC1pbmRleCBoZWlnaHRtYXApXVxuICAgICh3aGVuIChhbmQgKDw9IDAgeCBsYXN0KVxuICAgICAgICAgICAgICAgKDw9IDAgeSBsYXN0KSlcbiAgICAgIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCB4IHkpKSkpXG5cbihkZWZuIGhlaWdodG1hcC1zZXQhIFtoZWlnaHRtYXAgeCB5IHZhbF1cbiAgKC5zZXQgaGVpZ2h0bWFwIHggeSB2YWwpKVxuXG4oZGVmbiBoZWlnaHRtYXAtc2V0LWlmLXVuc2V0ISBbaGVpZ2h0bWFwIHggeSB2YWxdXG4gICh3aGVuICg9PSAwIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCB4IHkpKVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgeCB5IHZhbCkpKVxuXG5cbihkZWZuIG5vcm1hbGl6ZSBbaGVpZ2h0bWFwXVxuICAobGV0IFttYXggKC0gSW5maW5pdHkpXG4gICAgICAgIG1pbiBJbmZpbml0eV1cbiAgICAoZG8tbmRhcnJheS1lbCBlbCBoZWlnaHRtYXBcbiAgICAgICh3aGVuICg8IG1heCBlbCkgKHNldCEgbWF4IGVsKSlcbiAgICAgICh3aGVuICg+IG1pbiBlbCkgKHNldCEgbWluIGVsKSkpXG4gICAgKGxldCBbc3BhbiAoLSBtYXggbWluKV1cbiAgICAgIChkby1uZGFycmF5IFt4IHldIGhlaWdodG1hcFxuICAgICAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIHggeVxuICAgICAgICAgICAgICAgICAgICAgICAgKC8gKC0gKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwIHggeSkgbWluKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhbikpKSkpKVxuXG5cbihkZWZuIG1ha2UtaGVpZ2h0bWFwIFtleHBvbmVudF1cbiAgKGxldCBbcmVzb2x1dGlvbiAoKyAoTWF0aC5wb3cgMiBleHBvbmVudCkgMSldXG4gICAgKGxldCBbaGVpZ2h0bWFwIChuZGFycmF5IChuZXcgRmxvYXQ2NEFycmF5ICgqIHJlc29sdXRpb24gcmVzb2x1dGlvbikpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtyZXNvbHV0aW9uIHJlc29sdXRpb25dKV1cbiAgICAgIChzZXQhIGhlaWdodG1hcC5leHBvbmVudCBleHBvbmVudClcbiAgICAgIChzZXQhIGhlaWdodG1hcC5yZXNvbHV0aW9uIHJlc29sdXRpb24pXG4gICAgICAoc2V0ISBoZWlnaHRtYXAubGFzdCAoZGVjIHJlc29sdXRpb24pKVxuICAgICAgaGVpZ2h0bWFwKSkpXG5cblxuKGRlZm4gdG9wLWxlZnQtY29ybmVyIFtoZWlnaHRtYXBdXG4gIChsZXQgW2NlbnRlciAoaGVpZ2h0bWFwLWNlbnRlci1pbmRleCBoZWlnaHRtYXApXVxuICAgICgtPiBoZWlnaHRtYXBcbiAgICAgICgubG8gMCAwKVxuICAgICAgKC5oaSAoaW5jIGNlbnRlcikgKGluYyBjZW50ZXIpKSkpKVxuXG4oZGVmbiB0b3AtcmlnaHQtY29ybmVyIFtoZWlnaHRtYXBdXG4gIChsZXQgW2NlbnRlciAoaGVpZ2h0bWFwLWNlbnRlci1pbmRleCBoZWlnaHRtYXApXVxuICAgICgtPiBoZWlnaHRtYXBcbiAgICAgICgubG8gY2VudGVyIDApXG4gICAgICAoLmhpIChpbmMgY2VudGVyKSAoaW5jIGNlbnRlcikpKSkpXG5cbihkZWZuIGJvdHRvbS1sZWZ0LWNvcm5lciBbaGVpZ2h0bWFwXVxuICAobGV0IFtjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAoLT4gaGVpZ2h0bWFwXG4gICAgICAoLmxvIDAgY2VudGVyKVxuICAgICAgKC5oaSAoaW5jIGNlbnRlcikgKGluYyBjZW50ZXIpKSkpKVxuXG4oZGVmbiBib3R0b20tcmlnaHQtY29ybmVyIFtoZWlnaHRtYXBdXG4gIChsZXQgW2NlbnRlciAoaGVpZ2h0bWFwLWNlbnRlci1pbmRleCBoZWlnaHRtYXApXVxuICAgICgtPiBoZWlnaHRtYXBcbiAgICAgICgubG8gY2VudGVyIGNlbnRlcilcbiAgICAgICguaGkgKGluYyBjZW50ZXIpIChpbmMgY2VudGVyKSkpKSlcblxuXG47IERpYW1vbmQtU3F1YXJlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4oZGVmbiBkcy1pbml0LWNvcm5lcnMgW2hlaWdodG1hcF1cbiAgKGxldCBbbGFzdCAoaGVpZ2h0bWFwLWxhc3QtaW5kZXggaGVpZ2h0bWFwKV1cbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIDAgICAgMCAgICAocmFuZCkpXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCAwICAgIGxhc3QgKHJhbmQpKVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgbGFzdCAwICAgIChyYW5kKSlcbiAgICAoaGVpZ2h0bWFwLXNldCEgaGVpZ2h0bWFwIGxhc3QgbGFzdCAocmFuZCkpKSlcblxuKGRlZm4gZHMtc3F1YXJlIFtoZWlnaHRtYXAgeCB5IHJhZGl1cyBzcHJlYWRdXG4gIChsZXQgW25ldy1oZWlnaHQgKGppdHRlclxuICAgICAgICAgICAgICAgICAgICAgKGF2ZXJhZ2U0XG4gICAgICAgICAgICAgICAgICAgICAgIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCAoLSB4IHJhZGl1cykgKC0geSByYWRpdXMpKVxuICAgICAgICAgICAgICAgICAgICAgICAoaGVpZ2h0bWFwLWdldCBoZWlnaHRtYXAgKC0geCByYWRpdXMpICgrIHkgcmFkaXVzKSlcbiAgICAgICAgICAgICAgICAgICAgICAgKGhlaWdodG1hcC1nZXQgaGVpZ2h0bWFwICgrIHggcmFkaXVzKSAoLSB5IHJhZGl1cykpXG4gICAgICAgICAgICAgICAgICAgICAgIChoZWlnaHRtYXAtZ2V0IGhlaWdodG1hcCAoKyB4IHJhZGl1cykgKCsgeSByYWRpdXMpKSlcbiAgICAgICAgICAgICAgICAgICAgIHNwcmVhZCldXG4gICAgKGhlaWdodG1hcC1zZXQhIGhlaWdodG1hcCB4IHkgbmV3LWhlaWdodCkpKVxuXG4oZGVmbiBkcy1kaWFtb25kIFtoZWlnaHRtYXAgeCB5IHJhZGl1cyBzcHJlYWRdXG4gIChsZXQgW25ldy1oZWlnaHQgKGppdHRlclxuICAgICAgICAgICAgICAgICAgICAgKHNhZmUtYXZlcmFnZVxuICAgICAgICAgICAgICAgICAgICAgICAoaGVpZ2h0bWFwLWdldC1zYWZlIGhlaWdodG1hcCAoLSB4IHJhZGl1cykgeSlcbiAgICAgICAgICAgICAgICAgICAgICAgKGhlaWdodG1hcC1nZXQtc2FmZSBoZWlnaHRtYXAgKCsgeCByYWRpdXMpIHkpXG4gICAgICAgICAgICAgICAgICAgICAgIChoZWlnaHRtYXAtZ2V0LXNhZmUgaGVpZ2h0bWFwIHggKC0geSByYWRpdXMpKVxuICAgICAgICAgICAgICAgICAgICAgICAoaGVpZ2h0bWFwLWdldC1zYWZlIGhlaWdodG1hcCB4ICgrIHkgcmFkaXVzKSkpXG4gICAgICAgICAgICAgICAgICAgICBzcHJlYWQpXVxuICAgIChoZWlnaHRtYXAtc2V0ISBoZWlnaHRtYXAgeCB5IG5ldy1oZWlnaHQpKSlcblxuXG4oZGVmbiBkcy1zcXVhcmVzIFtoZWlnaHRtYXAgcmFkaXVzIHNwcmVhZF1cbiAgKGRvLXN0cmlkZSBbeCB5XSByYWRpdXMgKGhlaWdodG1hcC1yZXNvbHV0aW9uIGhlaWdodG1hcCkgKCogMiByYWRpdXMpXG4gICAgKGRzLXNxdWFyZSBoZWlnaHRtYXAgeCB5IHJhZGl1cyBzcHJlYWQpKSlcblxuKGRlZm4gZHMtZGlhbW9uZHMgW2hlaWdodG1hcCByYWRpdXMgc3ByZWFkXVxuICAobGV0IFtzaXplIChoZWlnaHRtYXAtcmVzb2x1dGlvbiBoZWlnaHRtYXApXVxuICAgIChkby1zdHJpZGUgW3ldIDAgc2l6ZSByYWRpdXNcbiAgICAgIChsZXQgW3NoaWZ0IChpZiAoZXZlbj8gKC8geSByYWRpdXMpKSByYWRpdXMgMCldXG4gICAgICAgIChkby1zdHJpZGUgW3hdIHNoaWZ0IHNpemUgKCogMiByYWRpdXMpXG4gICAgICAgICAgKGRzLWRpYW1vbmQgaGVpZ2h0bWFwIHggeSByYWRpdXMgc3ByZWFkKSkpKSkpXG5cbihkZWZuIGRpYW1vbmQtc3F1YXJlIFtoZWlnaHRtYXBdXG4gIChsZXQgW2luaXRpYWwtc3ByZWFkIDAuM1xuICAgICAgICBzcHJlYWQtcmVkdWN0aW9uIDAuNVxuICAgICAgICBjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKVxuICAgICAgICBzaXplIChhZ2V0IGhlaWdodG1hcC5zaGFwZSAwKV1cbiAgICAoZHMtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgICAobG9vcCBbcmFkaXVzIGNlbnRlclxuICAgICAgICAgICBzcHJlYWQgaW5pdGlhbC1zcHJlYWRdXG4gICAgICAod2hlbiAoPj0gcmFkaXVzIDEpXG4gICAgICAgIChkcy1zcXVhcmVzIGhlaWdodG1hcCByYWRpdXMgc3ByZWFkKVxuICAgICAgICAoZHMtZGlhbW9uZHMgaGVpZ2h0bWFwIHJhZGl1cyBzcHJlYWQpXG4gICAgICAgIChyZWN1ciAoLyByYWRpdXMgMilcbiAgICAgICAgICAgICAgICgqIHNwcmVhZCBzcHJlYWQtcmVkdWN0aW9uKSkpKVxuICAgIChub3JtYWxpemUgaGVpZ2h0bWFwKSkpXG5cblxuKGRlZm4gZGlhbW9uZC1zcXVhcmUtMSBbaGVpZ2h0bWFwXVxuICAoZHMtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgKG5vcm1hbGl6ZSBoZWlnaHRtYXApKVxuXG4oZGVmbiBkaWFtb25kLXNxdWFyZS0yIFtoZWlnaHRtYXBdXG4gIChsZXQgW2luaXRpYWwtc3ByZWFkIDAuM1xuICAgICAgICBzcHJlYWQtcmVkdWN0aW9uIDAuNVxuICAgICAgICBjZW50ZXIgKGhlaWdodG1hcC1jZW50ZXItaW5kZXggaGVpZ2h0bWFwKVxuICAgICAgICBzaXplIChhZ2V0IGhlaWdodG1hcC5zaGFwZSAwKV1cbiAgICAoZHMtaW5pdC1jb3JuZXJzIGhlaWdodG1hcClcbiAgICAoZHMtc3F1YXJlcyBoZWlnaHRtYXAgY2VudGVyIGluaXRpYWwtc3ByZWFkKVxuICAgIChub3JtYWxpemUgaGVpZ2h0bWFwKSkpXG5cbihkZWZuIGRpYW1vbmQtc3F1YXJlLTMgW2hlaWdodG1hcF1cbiAgKGxldCBbaW5pdGlhbC1zcHJlYWQgMC4zXG4gICAgICAgIHNwcmVhZC1yZWR1Y3Rpb24gMC41XG4gICAgICAgIGNlbnRlciAoaGVpZ2h0bWFwLWNlbnRlci1pbmRleCBoZWlnaHRtYXApXG4gICAgICAgIHNpemUgKGFnZXQgaGVpZ2h0bWFwLnNoYXBlIDApXVxuICAgIChkcy1pbml0LWNvcm5lcnMgaGVpZ2h0bWFwKVxuICAgIChkcy1zcXVhcmVzIGhlaWdodG1hcCBjZW50ZXIgaW5pdGlhbC1zcHJlYWQpXG4gICAgKGRzLWRpYW1vbmRzIGhlaWdodG1hcCBjZW50ZXIgaW5pdGlhbC1zcHJlYWQpXG4gICAgKGRzLXNxdWFyZXMgaGVpZ2h0bWFwICgvIGNlbnRlciAyKSAoKiBzcHJlYWQtcmVkdWN0aW9uIGluaXRpYWwtc3ByZWFkKSlcbiAgICAoZHMtZGlhbW9uZHMgaGVpZ2h0bWFwICgvIGNlbnRlciAyKSAoKiBzcHJlYWQtcmVkdWN0aW9uIGluaXRpYWwtc3ByZWFkKSlcbiAgICAobm9ybWFsaXplIGhlaWdodG1hcCkpKVxuXG5cbjsgVGhyZWUuanMgSGVscGVycyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbihkZWZuIG1ha2UtZGlyZWN0aW9uYWwtbGlnaHQgW11cbiAgKGxldCBbbGlnaHQgKG5ldyBUSFJFRS5EaXJlY3Rpb25hbExpZ2h0IDB4ZmZmZmZmIDEpXVxuICAgIChsaWdodC5wb3NpdGlvbi5zZXQgMTAwIDAgMTUwKVxuICAgIGxpZ2h0KSlcblxuKGRlZm4gbWFrZS1jYW1lcmEgW11cbiAgKGxldCBbY2FtZXJhIChuZXcgVEhSRUUuUGVyc3BlY3RpdmVDYW1lcmFcbiAgICAgICAgICAgICAgICAgICAgNTUsXG4gICAgICAgICAgICAgICAgICAgICgvIHdpZHRoIGhlaWdodClcbiAgICAgICAgICAgICAgICAgICAgMC4xLFxuICAgICAgICAgICAgICAgICAgICAxMDAwKV1cbiAgICAoY2FtZXJhLnBvc2l0aW9uLnNldCAwIC0xMDAgMTUwKVxuICAgIGNhbWVyYSkpXG5cbihkZWZuIG1ha2UtcmVuZGVyZXIgW11cbiAgKGxldCBbcmVuZGVyZXIgKG5ldyBUSFJFRS5XZWJHTFJlbmRlcmVyIHs6YW50aWFsaWFzIGZhbHNlfSldXG4gICAgKHJlbmRlcmVyLnNldENsZWFyQ29sb3IgMHhmZmZmZmYpXG4gICAgKHJlbmRlcmVyLnNldFNpemUgd2lkdGggaGVpZ2h0KVxuICAgIChyZW5kZXJlci5zZXRQaXhlbFJhdGlvIDIpXG4gICAgcmVuZGVyZXIpKVxuXG4oZGVmbiBtYWtlLWdlb21ldHJ5IFtoZWlnaHRtYXBdXG4gIChsZXQgW3Jlc29sdXRpb24gKGFnZXQgaGVpZ2h0bWFwLnNoYXBlIDApXG4gICAgICAgIGdlb21ldHJ5IChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeVxuICAgICAgICAgICAgICAgICAgICAgIHRlcnJhaW4tc2l6ZVxuICAgICAgICAgICAgICAgICAgICAgIHRlcnJhaW4tc2l6ZVxuICAgICAgICAgICAgICAgICAgICAgICgtIHJlc29sdXRpb24gMSlcbiAgICAgICAgICAgICAgICAgICAgICAoLSByZXNvbHV0aW9uIDEpKV1cbiAgICBnZW9tZXRyeSkpXG5cbihkZWZuIG1ha2UtY29udHJvbHMgW2NhbWVyYSByZW5kZXJlcl1cbiAgKGxldCBbY29udHJvbHMgKG5ldyBUSFJFRS5UcmFja2JhbGxDb250cm9scyBjYW1lcmEgcmVuZGVyZXIuZG9tRWxlbWVudCldXG4gICAgKHNldCEgY29udHJvbHMucm90YXRlU3BlZWQgMS40KVxuICAgIChzZXQhIGNvbnRyb2xzLnpvb21TcGVlZCAwLjUpXG4gICAgKHNldCEgY29udHJvbHMuc3RhdGljTW92aW5nIHRydWUpXG4gICAgKHNldCEgY29udHJvbHMuZHluYW1pY0RhbXBpbmdGYWN0b3IgMC4zKVxuICAgIGNvbnRyb2xzKSlcblxuKGRlZm4gbWFrZS1wbGFuZSBbZ2VvbWV0cnldXG4gIChsZXQgW21hdGVyaWFsIChuZXcgVEhSRUUuTWVzaExhbWJlcnRNYXRlcmlhbFxuICAgICAgICAgICAgICAgICAgICAgIHs6d2lyZWZyYW1lIHdpcmVmcmFtZVxuICAgICAgICAgICAgICAgICAgICAgICA6d2lyZWZyYW1lTGluZXdpZHRoIHdpcmVmcmFtZS13aWR0aFxuICAgICAgICAgICAgICAgICAgICAgICA6Y29sb3IgMHgwMGJiMDB9KV1cbiAgICAobmV3IFRIUkVFLk1lc2ggZ2VvbWV0cnkgbWF0ZXJpYWwpKSlcblxuXG4oZGVmbiBhdHRhY2gtdG8tZG9tIFtyZW5kZXJlciBlbC1uYW1lIHJlZnJlc2gtZm5dXG4gIChsZXQgW2NvbnRhaW5lciAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQgZWwtbmFtZSlcbiAgICAgICAgc2V0dGluZ3MgKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgXCJkaXZcIilcbiAgICAgICAgcmVmcmVzaC1idXR0b24gKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgXCJidXR0b25cIilcbiAgICAgICAgYnV0dG9uLXRleHQgKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlIFwiUmVmcmVzaFwiKVxuICAgICAgICBjYW5jZWwtc2Nyb2xsIChmbiBbZV0gKC5wcmV2ZW50RGVmYXVsdCBlKSldXG4gICAgKHNldCEgcmVmcmVzaC1idXR0b24ub25jbGljayByZWZyZXNoLWZuKVxuICAgIChzZXQhIHJlbmRlcmVyLmRvbUVsZW1lbnQub25tb3VzZXdoZWVsIGNhbmNlbC1zY3JvbGwpXG4gICAgKHJlbmRlcmVyLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciBcIk1vek1vdXNlUGl4ZWxTY3JvbGxcIiBjYW5jZWwtc2Nyb2xsIGZhbHNlKVxuICAgICguYXBwZW5kQ2hpbGQgcmVmcmVzaC1idXR0b24gYnV0dG9uLXRleHQpXG4gICAgKC5hcHBlbmRDaGlsZCBjb250YWluZXIgcmVuZGVyZXIuZG9tRWxlbWVudClcbiAgICAoLmFwcGVuZENoaWxkIGNvbnRhaW5lciBzZXR0aW5ncylcbiAgICAoLmFwcGVuZENoaWxkIHNldHRpbmdzIHJlZnJlc2gtYnV0dG9uKSkpXG5cblxuKGRlZm4gdXBkYXRlLWdlb21ldHJ5IFtnZW9tZXRyeSBoZWlnaHRtYXBdXG4gIChsb29wIFtpIDBdXG4gICAgKGlmICg8IGkgZ2VvbWV0cnkudmVydGljZXMubGVuZ3RoKVxuICAgICAgKGRvIChzZXQhICguLXogKGFnZXQgZ2VvbWV0cnkudmVydGljZXMgaSkpXG4gICAgICAgICAgICAgICAgKCogdGVycmFpbi1oZWlnaHQgKGFnZXQgKC4tZGF0YSBoZWlnaHRtYXApIGkpKSlcbiAgICAgICAgKHJlY3VyICgrIGkgMSkpKSkpXG4gIChnZW9tZXRyeS5jb21wdXRlVmVydGV4Tm9ybWFscylcbiAgZ2VvbWV0cnkpXG5cblxuOyBNYWluIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKGRlZm4gbWFrZS1kZW1vIFtlbGVtZW50LWlkIGFsZ29yaXRobSBzaXplXVxuICAoZGVmIHNjZW5lIChuZXcgVEhSRUUuU2NlbmUpKVxuICAoc2NlbmUuYWRkIChuZXcgVEhSRUUuQXhpc0hlbHBlciAxMDApKVxuXG4gIChkZWYgY2xvY2sgKG5ldyBUSFJFRS5DbG9jaykpXG4gIChkZWYgY2FtZXJhIChtYWtlLWNhbWVyYSkpXG4gIChkZWYgcmVuZGVyZXIgKG1ha2UtcmVuZGVyZXIpKVxuXG4gIChkZWYgZ2VvbWV0cnkpXG4gIChkZWYgcGxhbmUpXG5cbiAgKHNjZW5lLmFkZCAobWFrZS1kaXJlY3Rpb25hbC1saWdodCkpXG4gIChzY2VuZS5hZGQgKG5ldyBUSFJFRS5BbWJpZW50TGlnaHQgMHhmZmZmZmYgMC4wNSkpXG5cbiAgKGRlZm4gcmVmcmVzaCBbXVxuICAgIChsZXQgW2hlaWdodG1hcCAobWFrZS1oZWlnaHRtYXAgc2l6ZSldXG4gICAgICAobCBcIkdlbmVyYXRpbmcgdGVycmFpbi4uLlwiKVxuICAgICAgKHRpbWUgKGFsZ29yaXRobSBoZWlnaHRtYXApKVxuXG4gICAgICAobCBcIlJlYnVpbGRpbmcgZ2VvbWV0cnkuLi5cIilcbiAgICAgICh0aW1lXG4gICAgICAgIChzZXQhIGdlb21ldHJ5IChtYWtlLWdlb21ldHJ5IGhlaWdodG1hcCkpXG4gICAgICAgICh1cGRhdGUtZ2VvbWV0cnkgZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcblxuICAgICAgKGwgXCJSZWJ1aWxkaW5nIHBsYW5lLi4uXCIpXG4gICAgICAodGltZVxuICAgICAgICAoc2NlbmUucmVtb3ZlIHBsYW5lKVxuICAgICAgICAoc2V0ISBwbGFuZSAobWFrZS1wbGFuZSBnZW9tZXRyeSkpXG4gICAgICAgIChzY2VuZS5hZGQgcGxhbmUpKSkpXG5cbiAgKGF0dGFjaC10by1kb20gcmVuZGVyZXIgZWxlbWVudC1pZCByZWZyZXNoKVxuICAoZGVmIGNvbnRyb2xzIChtYWtlLWNvbnRyb2xzIGNhbWVyYSByZW5kZXJlcikpXG5cbiAgKGRlZm4gcmVuZGVyIFtdXG4gICAgKGxldCBbZGVsdGEgKGNsb2NrLmdldERlbHRhKV1cbiAgICAgIChyZXF1ZXN0QW5pbWF0aW9uRnJhbWUgcmVuZGVyKVxuICAgICAgKC51cGRhdGUgY29udHJvbHMgZGVsdGEpXG4gICAgICAocmVuZGVyZXIucmVuZGVyIHNjZW5lIGNhbWVyYSkpKVxuXG4gIChyZWZyZXNoKVxuICAocmVuZGVyKVxuXG4gIG5pbClcblxuKGRlZm4gbWFrZS1maW5hbCBbZWxlbWVudC1pZF1cbiAgKGRlZiBzY2VuZSAobmV3IFRIUkVFLlNjZW5lKSlcbiAgKHNjZW5lLmFkZCAobmV3IFRIUkVFLkF4aXNIZWxwZXIgMTAwKSlcblxuICAoZGVmIGNsb2NrIChuZXcgVEhSRUUuQ2xvY2spKVxuICAoZGVmIGNhbWVyYSAobWFrZS1jYW1lcmEpKVxuICAoZGVmIHJlbmRlcmVyIChtYWtlLXJlbmRlcmVyKSlcblxuICAoZGVmIGdlb21ldHJ5KVxuICAoZGVmIHBsYW5lKVxuXG4gIChzY2VuZS5hZGQgKG1ha2UtZGlyZWN0aW9uYWwtbGlnaHQpKVxuICAoc2NlbmUuYWRkIChuZXcgVEhSRUUuQW1iaWVudExpZ2h0IDB4ZmZmZmZmIDAuMDUpKVxuXG4gIChkZWZuIHJlZnJlc2ggW11cbiAgICAobGV0IFtoZWlnaHRtYXAgKG1ha2UtaGVpZ2h0bWFwIDYpXVxuICAgICAgKGwgXCJHZW5lcmF0aW5nIHRlcnJhaW4uLi5cIilcbiAgICAgICh0aW1lIChkaWFtb25kLXNxdWFyZSBoZWlnaHRtYXApKVxuXG4gICAgICAobCBcIlJlYnVpbGRpbmcgZ2VvbWV0cnkuLi5cIilcbiAgICAgICh0aW1lXG4gICAgICAgIChzZXQhIGdlb21ldHJ5IChtYWtlLWdlb21ldHJ5IGhlaWdodG1hcCkpXG4gICAgICAgICh1cGRhdGUtZ2VvbWV0cnkgZ2VvbWV0cnkgaGVpZ2h0bWFwKSlcblxuICAgICAgKGwgXCJSZWJ1aWxkaW5nIHBsYW5lLi4uXCIpXG4gICAgICAodGltZVxuICAgICAgICAoc2NlbmUucmVtb3ZlIHBsYW5lKVxuICAgICAgICAoc2V0ISBwbGFuZSAobWFrZS1wbGFuZSBnZW9tZXRyeSkpXG4gICAgICAgIChzY2VuZS5hZGQgcGxhbmUpKSkpXG5cbiAgKGF0dGFjaC10by1kb20gcmVuZGVyZXIgZWxlbWVudC1pZCByZWZyZXNoKVxuICAoZGVmIGNvbnRyb2xzIChtYWtlLWNvbnRyb2xzIGNhbWVyYSByZW5kZXJlcikpXG5cbiAgKGRlZm4gcmVuZGVyIFtdXG4gICAgKGxldCBbZGVsdGEgKGNsb2NrLmdldERlbHRhKV1cbiAgICAgIChyZXF1ZXN0QW5pbWF0aW9uRnJhbWUgcmVuZGVyKVxuICAgICAgKC51cGRhdGUgY29udHJvbHMgZGVsdGEpXG4gICAgICAocmVuZGVyZXIucmVuZGVyIHNjZW5lIGNhbWVyYSkpKVxuXG4gIChyZWZyZXNoKVxuICAocmVuZGVyKVxuXG4gIG5pbClcblxuKGRlZm4gcnVuIFtdXG4gIChtYWtlLWRlbW8gXCJkZW1vLTFcIiBkaWFtb25kLXNxdWFyZS0xIDIpXG4gIChtYWtlLWRlbW8gXCJkZW1vLTJcIiBkaWFtb25kLXNxdWFyZS0yIDQpXG4gIChtYWtlLWRlbW8gXCJkZW1vLTNcIiBkaWFtb25kLXNxdWFyZS0zIDQpXG4gIChtYWtlLWZpbmFsIFwiZGVtby1maW5hbFwiKSlcblxuKCQgcnVuKVxuXG5cbjsgdmltOiBsdys9ZG8tdGltZXMgbHcrPWRvLW5lc3RlZCA6XG4iXX0=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/wisp/terrain3.wisp	Sat Jun 25 15:57:05 2016 +0000
@@ -0,0 +1,470 @@
+(ns demo
+  (:require [ndarray]))
+
+
+; Constants -------------------------------------------------------------------
+(def width 610)
+(def height 400)
+(def wireframe true)
+(def wireframe-width 1.2)
+(def terrain-height 50)
+(def terrain-size 100)
+
+; General Utilities -----------------------------------------------------------
+(defmacro when [condition & body]
+  `(if ~condition
+     (do ~@body)))
+
+(defmacro when-not [condition & body]
+  `(when (not ~condition)
+     ~@body))
+
+(defmacro -> [& operations]
+  (reduce
+    (fn [form operation]
+      (cons (first operation)
+            (cons form (rest operation))))
+    (first operations)
+    (rest operations)))
+
+
+(defn inc [x]
+  (+ x 1))
+
+(defn dec [x]
+  (- x 1))
+
+
+(defmacro do-times [varname limit & body]
+  (let [end (gensym)]
+    `(let [~end ~limit]
+       (loop [~varname 0]
+         (when (< ~varname ~end)
+           ~@body
+           (recur (inc ~varname)))))))
+
+(defmacro do-stride [varnames start-form end-form stride-form & body]
+  (let [stride (gensym "stride")
+        start (gensym "start")
+        end (gensym "end")
+        build (fn build [vars]
+                (if (empty? vars)
+                  `(do ~@body)
+                  (let [varname (first vars)]
+                    `(loop [~varname ~start]
+                       (when (< ~varname ~end)
+                         ~(build (rest vars))
+                         (recur (+ ~varname ~stride)))))))]
+    ; Fix the numbers once outside the nested loops,
+    ; and then build the guts.
+    `(let [~start ~start-form
+           ~end ~end-form
+           ~stride ~stride-form]
+       ~(build varnames))))
+
+
+(defmacro do-ndarray [vars array-form & body]
+  (let [array-var (gensym "array")
+        build (fn build [vars n]
+                (if (empty? vars)
+                  `(do ~@body)
+                  `(do-times ~(first vars) (aget (.-shape ~array-var) ~n)
+                     ~(build (rest vars) (inc n)))))]
+    `(let [~array-var ~array-form]
+       ~(build vars 0))))
+
+(defmacro do-ndarray-el [element array-form & body]
+  (let [index (gensym "index")
+        array (gensym "array")]
+    `(let [~array ~array-form]
+       (do-times ~index (.-length (.-data ~array))
+         (let [~element (aget (.-data ~array) ~index)]
+           ~@body)))))
+
+
+(defmacro inc! [place]
+  `(set! ~place (inc ~place)))
+
+(defmacro add! [place amount]
+  `(set! ~place (+ ~place ~amount)))
+
+
+(defmacro l [& forms]
+  `(console.log ~@forms))
+
+(defmacro time [& body]
+  (let [start (gensym)
+        end (gensym)
+        result (gensym)]
+    `(let [~start (.getTime (new Date))
+           ~result (do ~@body)
+           ~end (.getTime (new Date))]
+       (l (+ "Elapsed time: " (- ~end ~start) "ms."))
+       ~result)))
+
+
+(defn midpoint [a b]
+  (/ (+ a b) 2))
+
+(defn average2 [a b]
+  (/ (+ a b) 2))
+
+(defn average4 [a b c d]
+  (/ (+ a b c d) 4))
+
+(defn safe-average [a b c d]
+  (let [total 0 count 0]
+    (when a (add! total a) (inc! count))
+    (when b (add! total b) (inc! count))
+    (when c (add! total c) (inc! count))
+    (when d (add! total d) (inc! count))
+    (/ total count)))
+
+
+(defn even? [n]
+  (== 0 (mod n 2)))
+
+(defn odd? [n]
+  (== 1 (mod n 2)))
+
+
+; Randomness ------------------------------------------------------------------
+(defn rand []
+  (Math.random))
+
+(defn rand-around-zero [spread]
+  (- (* spread (rand) 2) spread))
+
+(defn jitter [value spread]
+  (+ value (rand-around-zero spread)))
+
+
+; Heightmap Helpers -----------------------------------------------------------
+(defn heightmap-resolution [heightmap]
+  (aget heightmap.shape 0))
+
+(defn heightmap-last-index [heightmap]
+  (dec (heightmap-resolution heightmap)))
+
+(defn heightmap-center-index [heightmap]
+  (midpoint 0 (heightmap-last-index heightmap)))
+
+
+(defn heightmap-get [heightmap x y]
+  (.get heightmap x y))
+
+(defn heightmap-get-safe [heightmap x y]
+  (let [last (heightmap-last-index heightmap)]
+    (when (and (<= 0 x last)
+               (<= 0 y last))
+      (heightmap-get heightmap x y))))
+
+(defn heightmap-set! [heightmap x y val]
+  (.set heightmap x y val))
+
+(defn heightmap-set-if-unset! [heightmap x y val]
+  (when (== 0 (heightmap-get heightmap x y))
+    (heightmap-set! heightmap x y val)))
+
+
+(defn normalize [heightmap]
+  (let [max (- Infinity)
+        min Infinity]
+    (do-ndarray-el el heightmap
+      (when (< max el) (set! max el))
+      (when (> min el) (set! min el)))
+    (let [span (- max min)]
+      (do-ndarray [x y] heightmap
+        (heightmap-set! heightmap x y
+                        (/ (- (heightmap-get heightmap x y) min)
+                           span))))))
+
+
+(defn make-heightmap [exponent]
+  (let [resolution (+ (Math.pow 2 exponent) 1)]
+    (let [heightmap (ndarray (new Float64Array (* resolution resolution))
+                             [resolution resolution])]
+      (set! heightmap.exponent exponent)
+      (set! heightmap.resolution resolution)
+      (set! heightmap.last (dec resolution))
+      heightmap)))
+
+
+(defn top-left-corner [heightmap]
+  (let [center (heightmap-center-index heightmap)]
+    (-> heightmap
+      (.lo 0 0)
+      (.hi (inc center) (inc center)))))
+
+(defn top-right-corner [heightmap]
+  (let [center (heightmap-center-index heightmap)]
+    (-> heightmap
+      (.lo center 0)
+      (.hi (inc center) (inc center)))))
+
+(defn bottom-left-corner [heightmap]
+  (let [center (heightmap-center-index heightmap)]
+    (-> heightmap
+      (.lo 0 center)
+      (.hi (inc center) (inc center)))))
+
+(defn bottom-right-corner [heightmap]
+  (let [center (heightmap-center-index heightmap)]
+    (-> heightmap
+      (.lo center center)
+      (.hi (inc center) (inc center)))))
+
+
+; Diamond-Square --------------------------------------------------------------
+(defn ds-init-corners [heightmap]
+  (let [last (heightmap-last-index heightmap)]
+    (heightmap-set! heightmap 0    0    (rand))
+    (heightmap-set! heightmap 0    last (rand))
+    (heightmap-set! heightmap last 0    (rand))
+    (heightmap-set! heightmap last last (rand))))
+
+(defn ds-square [heightmap x y radius spread]
+  (let [new-height (jitter
+                     (average4
+                       (heightmap-get heightmap (- x radius) (- y radius))
+                       (heightmap-get heightmap (- x radius) (+ y radius))
+                       (heightmap-get heightmap (+ x radius) (- y radius))
+                       (heightmap-get heightmap (+ x radius) (+ y radius)))
+                     spread)]
+    (heightmap-set! heightmap x y new-height)))
+
+(defn ds-diamond [heightmap x y radius spread]
+  (let [new-height (jitter
+                     (safe-average
+                       (heightmap-get-safe heightmap (- x radius) y)
+                       (heightmap-get-safe heightmap (+ x radius) y)
+                       (heightmap-get-safe heightmap x (- y radius))
+                       (heightmap-get-safe heightmap x (+ y radius)))
+                     spread)]
+    (heightmap-set! heightmap x y new-height)))
+
+
+(defn ds-squares [heightmap radius spread]
+  (do-stride [x y] radius (heightmap-resolution heightmap) (* 2 radius)
+    (ds-square heightmap x y radius spread)))
+
+(defn ds-diamonds [heightmap radius spread]
+  (let [size (heightmap-resolution heightmap)]
+    (do-stride [y] 0 size radius
+      (let [shift (if (even? (/ y radius)) radius 0)]
+        (do-stride [x] shift size (* 2 radius)
+          (ds-diamond heightmap x y radius spread))))))
+
+(defn diamond-square [heightmap]
+  (let [initial-spread 0.3
+        spread-reduction 0.5
+        center (heightmap-center-index heightmap)
+        size (aget heightmap.shape 0)]
+    (ds-init-corners heightmap)
+    (loop [radius center
+           spread initial-spread]
+      (when (>= radius 1)
+        (ds-squares heightmap radius spread)
+        (ds-diamonds heightmap radius spread)
+        (recur (/ radius 2)
+               (* spread spread-reduction))))
+    (normalize heightmap)))
+
+
+(defn diamond-square-1 [heightmap]
+  (ds-init-corners heightmap)
+  (normalize heightmap))
+
+(defn diamond-square-2 [heightmap]
+  (let [initial-spread 0.3
+        spread-reduction 0.5
+        center (heightmap-center-index heightmap)
+        size (aget heightmap.shape 0)]
+    (ds-init-corners heightmap)
+    (ds-squares heightmap center initial-spread)
+    (normalize heightmap)))
+
+(defn diamond-square-3 [heightmap]
+  (let [initial-spread 0.3
+        spread-reduction 0.5
+        center (heightmap-center-index heightmap)
+        size (aget heightmap.shape 0)]
+    (ds-init-corners heightmap)
+    (ds-squares heightmap center initial-spread)
+    (ds-diamonds heightmap center initial-spread)
+    (ds-squares heightmap (/ center 2) (* spread-reduction initial-spread))
+    (ds-diamonds heightmap (/ center 2) (* spread-reduction initial-spread))
+    (normalize heightmap)))
+
+
+; Three.js Helpers ------------------------------------------------------------
+(defn make-directional-light []
+  (let [light (new THREE.DirectionalLight 0xffffff 1)]
+    (light.position.set 100 0 150)
+    light))
+
+(defn make-camera []
+  (let [camera (new THREE.PerspectiveCamera
+                    55,
+                    (/ width height)
+                    0.1,
+                    1000)]
+    (camera.position.set 0 -100 150)
+    camera))
+
+(defn make-renderer []
+  (let [renderer (new THREE.WebGLRenderer {:antialias false})]
+    (renderer.setClearColor 0xffffff)
+    (renderer.setSize width height)
+    (renderer.setPixelRatio 2)
+    renderer))
+
+(defn make-geometry [heightmap]
+  (let [resolution (aget heightmap.shape 0)
+        geometry (new THREE.PlaneGeometry
+                      terrain-size
+                      terrain-size
+                      (- resolution 1)
+                      (- resolution 1))]
+    geometry))
+
+(defn make-controls [camera renderer]
+  (let [controls (new THREE.TrackballControls camera renderer.domElement)]
+    (set! controls.rotateSpeed 1.4)
+    (set! controls.zoomSpeed 0.5)
+    (set! controls.staticMoving true)
+    (set! controls.dynamicDampingFactor 0.3)
+    controls))
+
+(defn make-plane [geometry]
+  (let [material (new THREE.MeshLambertMaterial
+                      {:wireframe wireframe
+                       :wireframeLinewidth wireframe-width
+                       :color 0x00bb00})]
+    (new THREE.Mesh geometry material)))
+
+
+(defn attach-to-dom [renderer el-name refresh-fn]
+  (let [container (document.getElementById el-name)
+        settings (document.createElement "div")
+        refresh-button (document.createElement "button")
+        button-text (document.createTextNode "Refresh")
+        cancel-scroll (fn [e] (.preventDefault e))]
+    (set! refresh-button.onclick refresh-fn)
+    (set! renderer.domElement.onmousewheel cancel-scroll)
+    (renderer.domElement.addEventListener "MozMousePixelScroll" cancel-scroll false)
+    (.appendChild refresh-button button-text)
+    (.appendChild container renderer.domElement)
+    (.appendChild container settings)
+    (.appendChild settings refresh-button)))
+
+
+(defn update-geometry [geometry heightmap]
+  (loop [i 0]
+    (if (< i geometry.vertices.length)
+      (do (set! (.-z (aget geometry.vertices i))
+                (* terrain-height (aget (.-data heightmap) i)))
+        (recur (+ i 1)))))
+  (geometry.computeVertexNormals)
+  geometry)
+
+
+; Main ------------------------------------------------------------------------
+(defn make-demo [element-id algorithm size]
+  (def scene (new THREE.Scene))
+  (scene.add (new THREE.AxisHelper 100))
+
+  (def clock (new THREE.Clock))
+  (def camera (make-camera))
+  (def renderer (make-renderer))
+
+  (def geometry)
+  (def plane)
+
+  (scene.add (make-directional-light))
+  (scene.add (new THREE.AmbientLight 0xffffff 0.05))
+
+  (defn refresh []
+    (let [heightmap (make-heightmap size)]
+      (l "Generating terrain...")
+      (time (algorithm heightmap))
+
+      (l "Rebuilding geometry...")
+      (time
+        (set! geometry (make-geometry heightmap))
+        (update-geometry geometry heightmap))
+
+      (l "Rebuilding plane...")
+      (time
+        (scene.remove plane)
+        (set! plane (make-plane geometry))
+        (scene.add plane))))
+
+  (attach-to-dom renderer element-id refresh)
+  (def controls (make-controls camera renderer))
+
+  (defn render []
+    (let [delta (clock.getDelta)]
+      (requestAnimationFrame render)
+      (.update controls delta)
+      (renderer.render scene camera)))
+
+  (refresh)
+  (render)
+
+  nil)
+
+(defn make-final [element-id]
+  (def scene (new THREE.Scene))
+  (scene.add (new THREE.AxisHelper 100))
+
+  (def clock (new THREE.Clock))
+  (def camera (make-camera))
+  (def renderer (make-renderer))
+
+  (def geometry)
+  (def plane)
+
+  (scene.add (make-directional-light))
+  (scene.add (new THREE.AmbientLight 0xffffff 0.05))
+
+  (defn refresh []
+    (let [heightmap (make-heightmap 6)]
+      (l "Generating terrain...")
+      (time (diamond-square heightmap))
+
+      (l "Rebuilding geometry...")
+      (time
+        (set! geometry (make-geometry heightmap))
+        (update-geometry geometry heightmap))
+
+      (l "Rebuilding plane...")
+      (time
+        (scene.remove plane)
+        (set! plane (make-plane geometry))
+        (scene.add plane))))
+
+  (attach-to-dom renderer element-id refresh)
+  (def controls (make-controls camera renderer))
+
+  (defn render []
+    (let [delta (clock.getDelta)]
+      (requestAnimationFrame render)
+      (.update controls delta)
+      (renderer.render scene camera)))
+
+  (refresh)
+  (render)
+
+  nil)
+
+(defn run []
+  (make-demo "demo-1" diamond-square-1 2)
+  (make-demo "demo-2" diamond-square-2 4)
+  (make-demo "demo-3" diamond-square-3 4)
+  (make-final "demo-final"))
+
+($ run)
+
+
+; vim: lw+=do-times lw+=do-nested :
--- a/settings.py	Mon Mar 07 13:44:20 2016 +0000
+++ b/settings.py	Sat Jun 25 15:57:05 2016 +0000
@@ -40,7 +40,8 @@
     '*': {
         '.less': ('hydeengine.media_processors.LessCSS',),
         '.js': ('hydeengine.media_processors.TemplateProcessor',
-                'hydeengine.media_processors.YUICompressor',)
+                # 'hydeengine.media_processors.YUICompressor',
+                )
     },
     'images/': {
         '.png': ('hydeengine.media_processors.Thumbnail',),