Skip to content

Instantly share code, notes, and snippets.

@jtenner
Last active November 14, 2017 22:40
Show Gist options
  • Save jtenner/d7d0641580f74ec913bc190aad43aa9e to your computer and use it in GitHub Desktop.
Save jtenner/d7d0641580f74ec913bc190aad43aa9e to your computer and use it in GitHub Desktop.
requirebin sketch
const rbush = require( "rbush" );
const ctx = document.createElement( "canvas" ).getContext( "2d" );
const width = ctx.canvas.width = 800;
const height = ctx.canvas.height = 600;
const e2d = require( "e2d" );
document.body.appendChild( ctx.canvas );
const tree = rbush();
const rects = [];
for ( let i = 0; i < 100; i++ ) {
const rectWidth = 10 + Math.random() * 90;
const rectHeight = 10 + Math.random() * 90;
const minX = 0 + Math.random() * ( width - rectWidth );
const minY = 0 + Math.random() * ( height - rectHeight );
const maxX = minX + rectWidth;
const maxY = minY + rectHeight;
const rect = {
rectWidth,
rectHeight,
minX,
minY,
maxX,
maxY,
fill: e2d.fillRect( minX, minY, rectWidth, rectHeight ),
};
rects.push( e2d.strokeRect( minX, minY, rectWidth, rectHeight ) );
tree.insert( rect );
}
e2d.initialize( ctx );
e2d.raf(frame => {
const { x, y } = e2d.mouseData( ctx );
const mouseRect = e2d.fillStyle( "red", e2d.strokeRect( x - 10, y - 10, 20, 20 ) );
e2d.render(
e2d.clearRect( width, height ),
tree.search({
minX: x - 10,
minY: y - 10,
maxX: x + 10,
maxY: y + 10
}).map(z => z.fill),
mouseRect,
rects,
ctx
);
});
setTimeout(function(){
;require=(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){
'use strict';
module.exports = partialSort;
// Floyd-Rivest selection algorithm:
// Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
// The k-th element will have the (k - left + 1)th smallest value in [left, right]
function partialSort(arr, k, left, right, compare) {
left = left || 0;
right = right || (arr.length - 1);
compare = compare || defaultCompare;
while (right > left) {
if (right - left > 600) {
var n = right - left + 1;
var m = k - left + 1;
var z = Math.log(n);
var s = 0.5 * Math.exp(2 * z / 3);
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
partialSort(arr, k, newLeft, newRight, compare);
}
var t = arr[k];
var i = left;
var j = right;
swap(arr, left, k);
if (compare(arr[right], t) > 0) swap(arr, left, right);
while (i < j) {
swap(arr, i, j);
i++;
j--;
while (compare(arr[i], t) < 0) i++;
while (compare(arr[j], t) > 0) j--;
}
if (compare(arr[left], t) === 0) swap(arr, left, j);
else {
j++;
swap(arr, j, right);
}
if (j <= k) left = j + 1;
if (k <= j) right = j - 1;
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
function defaultCompare(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
},{}],"rbush":[function(require,module,exports){
'use strict';
module.exports = rbush;
var quickselect = require('quickselect');
function rbush(maxEntries, format) {
if (!(this instanceof rbush)) return new rbush(maxEntries, format);
// max entries in a node is 9 by default; min node fill is 40% for best performance
this._maxEntries = Math.max(4, maxEntries || 9);
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
if (format) {
this._initFormat(format);
}
this.clear();
}
rbush.prototype = {
all: function () {
return this._all(this.data, []);
},
search: function (bbox) {
var node = this.data,
result = [],
toBBox = this.toBBox;
if (!intersects(bbox, node)) return result;
var nodesToSearch = [],
i, len, child, childBBox;
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child;
if (intersects(bbox, childBBox)) {
if (node.leaf) result.push(child);
else if (contains(bbox, childBBox)) this._all(child, result);
else nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return result;
},
collides: function (bbox) {
var node = this.data,
toBBox = this.toBBox;
if (!intersects(bbox, node)) return false;
var nodesToSearch = [],
i, len, child, childBBox;
while (node) {
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child;
if (intersects(bbox, childBBox)) {
if (node.leaf || contains(bbox, childBBox)) return true;
nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return false;
},
load: function (data) {
if (!(data && data.length)) return this;
if (data.length < this._minEntries) {
for (var i = 0, len = data.length; i < len; i++) {
this.insert(data[i]);
}
return this;
}
// recursively build the tree with the given data from stratch using OMT algorithm
var node = this._build(data.slice(), 0, data.length - 1, 0);
if (!this.data.children.length) {
// save as is if tree is empty
this.data = node;
} else if (this.data.height === node.height) {
// split root if trees have the same height
this._splitRoot(this.data, node);
} else {
if (this.data.height < node.height) {
// swap trees if inserted one is bigger
var tmpNode = this.data;
this.data = node;
node = tmpNode;
}
// insert the small tree into the large tree at appropriate level
this._insert(node, this.data.height - node.height - 1, true);
}
return this;
},
insert: function (item) {
if (item) this._insert(item, this.data.height - 1);
return this;
},
clear: function () {
this.data = createNode([]);
return this;
},
remove: function (item, equalsFn) {
if (!item) return this;
var node = this.data,
bbox = this.toBBox(item),
path = [],
indexes = [],
i, parent, index, goingUp;
// depth-first iterative tree traversal
while (node || path.length) {
if (!node) { // go up
node = path.pop();
parent = path[path.length - 1];
i = indexes.pop();
goingUp = true;
}
if (node.leaf) { // check current node
index = findItem(item, node.children, equalsFn);
if (index !== -1) {
// item found, remove the item and condense tree upwards
node.children.splice(index, 1);
path.push(node);
this._condense(path);
return this;
}
}
if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
path.push(node);
indexes.push(i);
i = 0;
parent = node;
node = node.children[0];
} else if (parent) { // go right
i++;
node = parent.children[i];
goingUp = false;
} else node = null; // nothing found
}
return this;
},
toBBox: function (item) { return item; },
compareMinX: compareNodeMinX,
compareMinY: compareNodeMinY,
toJSON: function () { return this.data; },
fromJSON: function (data) {
this.data = data;
return this;
},
_all: function (node, result) {
var nodesToSearch = [];
while (node) {
if (node.leaf) result.push.apply(result, node.children);
else nodesToSearch.push.apply(nodesToSearch, node.children);
node = nodesToSearch.pop();
}
return result;
},
_build: function (items, left, right, height) {
var N = right - left + 1,
M = this._maxEntries,
node;
if (N <= M) {
// reached leaf level; return leaf
node = createNode(items.slice(left, right + 1));
calcBBox(node, this.toBBox);
return node;
}
if (!height) {
// target height of the bulk-loaded tree
height = Math.ceil(Math.log(N) / Math.log(M));
// target number of root entries to maximize storage utilization
M = Math.ceil(N / Math.pow(M, height - 1));
}
node = createNode([]);
node.leaf = false;
node.height = height;
// split the items into M mostly square tiles
var N2 = Math.ceil(N / M),
N1 = N2 * Math.ceil(Math.sqrt(M)),
i, j, right2, right3;
multiSelect(items, left, right, N1, this.compareMinX);
for (i = left; i <= right; i += N1) {
right2 = Math.min(i + N1 - 1, right);
multiSelect(items, i, right2, N2, this.compareMinY);
for (j = i; j <= right2; j += N2) {
right3 = Math.min(j + N2 - 1, right2);
// pack each entry recursively
node.children.push(this._build(items, j, right3, height - 1));
}
}
calcBBox(node, this.toBBox);
return node;
},
_chooseSubtree: function (bbox, node, level, path) {
var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
while (true) {
path.push(node);
if (node.leaf || path.length - 1 === level) break;
minArea = minEnlargement = Infinity;
for (i = 0, len = node.children.length; i < len; i++) {
child = node.children[i];
area = bboxArea(child);
enlargement = enlargedArea(bbox, child) - area;
// choose entry with the least area enlargement
if (enlargement < minEnlargement) {
minEnlargement = enlargement;
minArea = area < minArea ? area : minArea;
targetNode = child;
} else if (enlargement === minEnlargement) {
// otherwise choose one with the smallest area
if (area < minArea) {
minArea = area;
targetNode = child;
}
}
}
node = targetNode || node.children[0];
}
return node;
},
_insert: function (item, level, isNode) {
var toBBox = this.toBBox,
bbox = isNode ? item : toBBox(item),
insertPath = [];
// find the best node for accommodating the item, saving all nodes along the path too
var node = this._chooseSubtree(bbox, this.data, level, insertPath);
// put the item into the node
node.children.push(item);
extend(node, bbox);
// split on node overflow; propagate upwards if necessary
while (level >= 0) {
if (insertPath[level].children.length > this._maxEntries) {
this._split(insertPath, level);
level--;
} else break;
}
// adjust bboxes along the insertion path
this._adjustParentBBoxes(bbox, insertPath, level);
},
// split overflowed node into two
_split: function (insertPath, level) {
var node = insertPath[level],
M = node.children.length,
m = this._minEntries;
this._chooseSplitAxis(node, m, M);
var splitIndex = this._chooseSplitIndex(node, m, M);
var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
newNode.height = node.height;
newNode.leaf = node.leaf;
calcBBox(node, this.toBBox);
calcBBox(newNode, this.toBBox);
if (level) insertPath[level - 1].children.push(newNode);
else this._splitRoot(node, newNode);
},
_splitRoot: function (node, newNode) {
// split root node
this.data = createNode([node, newNode]);
this.data.height = node.height + 1;
this.data.leaf = false;
calcBBox(this.data, this.toBBox);
},
_chooseSplitIndex: function (node, m, M) {
var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
minOverlap = minArea = Infinity;
for (i = m; i <= M - m; i++) {
bbox1 = distBBox(node, 0, i, this.toBBox);
bbox2 = distBBox(node, i, M, this.toBBox);
overlap = intersectionArea(bbox1, bbox2);
area = bboxArea(bbox1) + bboxArea(bbox2);
// choose distribution with minimum overlap
if (overlap < minOverlap) {
minOverlap = overlap;
index = i;
minArea = area < minArea ? area : minArea;
} else if (overlap === minOverlap) {
// otherwise choose distribution with minimum area
if (area < minArea) {
minArea = area;
index = i;
}
}
}
return index;
},
// sorts node children by the best axis for split
_chooseSplitAxis: function (node, m, M) {
var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
xMargin = this._allDistMargin(node, m, M, compareMinX),
yMargin = this._allDistMargin(node, m, M, compareMinY);
// if total distributions margin value is minimal for x, sort by minX,
// otherwise it's already sorted by minY
if (xMargin < yMargin) node.children.sort(compareMinX);
},
// total margin of all possible split distributions where each node is at least m full
_allDistMargin: function (node, m, M, compare) {
node.children.sort(compare);
var toBBox = this.toBBox,
leftBBox = distBBox(node, 0, m, toBBox),
rightBBox = distBBox(node, M - m, M, toBBox),
margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
i, child;
for (i = m; i < M - m; i++) {
child = node.children[i];
extend(leftBBox, node.leaf ? toBBox(child) : child);
margin += bboxMargin(leftBBox);
}
for (i = M - m - 1; i >= m; i--) {
child = node.children[i];
extend(rightBBox, node.leaf ? toBBox(child) : child);
margin += bboxMargin(rightBBox);
}
return margin;
},
_adjustParentBBoxes: function (bbox, path, level) {
// adjust bboxes along the given tree path
for (var i = level; i >= 0; i--) {
extend(path[i], bbox);
}
},
_condense: function (path) {
// go through the path, removing empty nodes and updating bboxes
for (var i = path.length - 1, siblings; i >= 0; i--) {
if (path[i].children.length === 0) {
if (i > 0) {
siblings = path[i - 1].children;
siblings.splice(siblings.indexOf(path[i]), 1);
} else this.clear();
} else calcBBox(path[i], this.toBBox);
}
},
_initFormat: function (format) {
// data format (minX, minY, maxX, maxY accessors)
// uses eval-type function compilation instead of just accepting a toBBox function
// because the algorithms are very sensitive to sorting functions performance,
// so they should be dead simple and without inner calls
var compareArr = ['return a', ' - b', ';'];
this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
this.toBBox = new Function('a',
'return {minX: a' + format[0] +
', minY: a' + format[1] +
', maxX: a' + format[2] +
', maxY: a' + format[3] + '};');
}
};
function findItem(item, items, equalsFn) {
if (!equalsFn) return items.indexOf(item);
for (var i = 0; i < items.length; i++) {
if (equalsFn(item, items[i])) return i;
}
return -1;
}
// calculate node's bbox from bboxes of its children
function calcBBox(node, toBBox) {
distBBox(node, 0, node.children.length, toBBox, node);
}
// min bounding rectangle of node children from k to p-1
function distBBox(node, k, p, toBBox, destNode) {
if (!destNode) destNode = createNode(null);
destNode.minX = Infinity;
destNode.minY = Infinity;
destNode.maxX = -Infinity;
destNode.maxY = -Infinity;
for (var i = k, child; i < p; i++) {
child = node.children[i];
extend(destNode, node.leaf ? toBBox(child) : child);
}
return destNode;
}
function extend(a, b) {
a.minX = Math.min(a.minX, b.minX);
a.minY = Math.min(a.minY, b.minY);
a.maxX = Math.max(a.maxX, b.maxX);
a.maxY = Math.max(a.maxY, b.maxY);
return a;
}
function compareNodeMinX(a, b) { return a.minX - b.minX; }
function compareNodeMinY(a, b) { return a.minY - b.minY; }
function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
function enlargedArea(a, b) {
return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
(Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
}
function intersectionArea(a, b) {
var minX = Math.max(a.minX, b.minX),
minY = Math.max(a.minY, b.minY),
maxX = Math.min(a.maxX, b.maxX),
maxY = Math.min(a.maxY, b.maxY);
return Math.max(0, maxX - minX) *
Math.max(0, maxY - minY);
}
function contains(a, b) {
return a.minX <= b.minX &&
a.minY <= b.minY &&
b.maxX <= a.maxX &&
b.maxY <= a.maxY;
}
function intersects(a, b) {
return b.minX <= a.maxX &&
b.minY <= a.maxY &&
b.maxX >= a.minX &&
b.maxY >= a.minY;
}
function createNode(children) {
return {
children: children,
height: 1,
leaf: true,
minX: Infinity,
minY: Infinity,
maxX: -Infinity,
maxY: -Infinity
};
}
// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
// combines selection algorithm with binary divide & conquer approach
function multiSelect(arr, left, right, n, compare) {
var stack = [left, right],
mid;
while (stack.length) {
right = stack.pop();
left = stack.pop();
if (right - left <= n) continue;
mid = left + Math.ceil((right - left) / n / 2) * n;
quickselect(arr, mid, left, right, compare);
stack.push(left, mid, mid, right);
}
}
},{"quickselect":1}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9xdWlja3NlbGVjdC9pbmRleC5qcyIsInJidXNoIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBwYXJ0aWFsU29ydDtcblxuLy8gRmxveWQtUml2ZXN0IHNlbGVjdGlvbiBhbGdvcml0aG06XG4vLyBSZWFycmFuZ2UgaXRlbXMgc28gdGhhdCBhbGwgaXRlbXMgaW4gdGhlIFtsZWZ0LCBrXSByYW5nZSBhcmUgc21hbGxlciB0aGFuIGFsbCBpdGVtcyBpbiAoaywgcmlnaHRdO1xuLy8gVGhlIGstdGggZWxlbWVudCB3aWxsIGhhdmUgdGhlIChrIC0gbGVmdCArIDEpdGggc21hbGxlc3QgdmFsdWUgaW4gW2xlZnQsIHJpZ2h0XVxuXG5mdW5jdGlvbiBwYXJ0aWFsU29ydChhcnIsIGssIGxlZnQsIHJpZ2h0LCBjb21wYXJlKSB7XG4gICAgbGVmdCA9IGxlZnQgfHwgMDtcbiAgICByaWdodCA9IHJpZ2h0IHx8IChhcnIubGVuZ3RoIC0gMSk7XG4gICAgY29tcGFyZSA9IGNvbXBhcmUgfHwgZGVmYXVsdENvbXBhcmU7XG5cbiAgICB3aGlsZSAocmlnaHQgPiBsZWZ0KSB7XG4gICAgICAgIGlmIChyaWdodCAtIGxlZnQgPiA2MDApIHtcbiAgICAgICAgICAgIHZhciBuID0gcmlnaHQgLSBsZWZ0ICsgMTtcbiAgICAgICAgICAgIHZhciBtID0gayAtIGxlZnQgKyAxO1xuICAgICAgICAgICAgdmFyIHogPSBNYXRoLmxvZyhuKTtcbiAgICAgICAgICAgIHZhciBzID0gMC41ICogTWF0aC5leHAoMiAqIHogLyAzKTtcbiAgICAgICAgICAgIHZhciBzZCA9IDAuNSAqIE1hdGguc3FydCh6ICogcyAqIChuIC0gcykgLyBuKSAqIChtIC0gbiAvIDIgPCAwID8gLTEgOiAxKTtcbiAgICAgICAgICAgIHZhciBuZXdMZWZ0ID0gTWF0aC5tYXgobGVmdCwgTWF0aC5mbG9vcihrIC0gbSAqIHMgLyBuICsgc2QpKTtcbiAgICAgICAgICAgIHZhciBuZXdSaWdodCA9IE1hdGgubWluKHJpZ2h0LCBNYXRoLmZsb29yKGsgKyAobiAtIG0pICogcyAvIG4gKyBzZCkpO1xuICAgICAgICAgICAgcGFydGlhbFNvcnQoYXJyLCBrLCBuZXdMZWZ0LCBuZXdSaWdodCwgY29tcGFyZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdCA9IGFycltrXTtcbiAgICAgICAgdmFyIGkgPSBsZWZ0O1xuICAgICAgICB2YXIgaiA9IHJpZ2h0O1xuXG4gICAgICAgIHN3YXAoYXJyLCBsZWZ0LCBrKTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYXJyW3JpZ2h0XSwgdCkgPiAwKSBzd2FwKGFyciwgbGVmdCwgcmlnaHQpO1xuXG4gICAgICAgIHdoaWxlIChpIDwgaikge1xuICAgICAgICAgICAgc3dhcChhcnIsIGksIGopO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgd2hpbGUgKGNvbXBhcmUoYXJyW2ldLCB0KSA8IDApIGkrKztcbiAgICAgICAgICAgIHdoaWxlIChjb21wYXJlKGFycltqXSwgdCkgPiAwKSBqLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29tcGFyZShhcnJbbGVmdF0sIHQpID09PSAwKSBzd2FwKGFyciwgbGVmdCwgaik7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgc3dhcChhcnIsIGosIHJpZ2h0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqIDw9IGspIGxlZnQgPSBqICsgMTtcbiAgICAgICAgaWYgKGsgPD0gaikgcmlnaHQgPSBqIC0gMTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoYXJyLCBpLCBqKSB7XG4gICAgdmFyIHRtcCA9IGFycltpXTtcbiAgICBhcnJbaV0gPSBhcnJbal07XG4gICAgYXJyW2pdID0gdG1wO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0Q29tcGFyZShhLCBiKSB7XG4gICAgcmV0dXJuIGEgPCBiID8gLTEgOiBhID4gYiA/IDEgOiAwO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJidXNoO1xuXG52YXIgcXVpY2tzZWxlY3QgPSByZXF1aXJlKCdxdWlja3NlbGVjdCcpO1xuXG5mdW5jdGlvbiByYnVzaChtYXhFbnRyaWVzLCBmb3JtYXQpIHtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgcmJ1c2gpKSByZXR1cm4gbmV3IHJidXNoKG1heEVudHJpZXMsIGZvcm1hdCk7XG5cbiAgICAvLyBtYXggZW50cmllcyBpbiBhIG5vZGUgaXMgOSBieSBkZWZhdWx0OyBtaW4gbm9kZSBmaWxsIGlzIDQwJSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCBtYXhFbnRyaWVzIHx8IDkpO1xuICAgIHRoaXMuX21pbkVudHJpZXMgPSBNYXRoLm1heCgyLCBNYXRoLmNlaWwodGhpcy5fbWF4RW50cmllcyAqIDAuNCkpO1xuXG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgICB0aGlzLl9pbml0Rm9ybWF0KGZvcm1hdCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbGVhcigpO1xufVxuXG5yYnVzaC5wcm90b3R5cGUgPSB7XG5cbiAgICBhbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FsbCh0aGlzLmRhdGEsIFtdKTtcbiAgICB9LFxuXG4gICAgc2VhcmNoOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgICB0b0JCb3ggPSB0aGlzLnRvQkJveDtcblxuICAgICAgICBpZiAoIWludGVyc2VjdHMoYmJveCwgbm9kZSkpIHJldHVybiByZXN1bHQ7XG5cbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXSxcbiAgICAgICAgICAgIGksIGxlbiwgY2hpbGQsIGNoaWxkQkJveDtcblxuICAgICAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGNoaWxkQkJveCA9IG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZDtcblxuICAgICAgICAgICAgICAgIGlmIChpbnRlcnNlY3RzKGJib3gsIGNoaWxkQkJveCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGUubGVhZikgcmVzdWx0LnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChjb250YWlucyhiYm94LCBjaGlsZEJCb3gpKSB0aGlzLl9hbGwoY2hpbGQsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2Ugbm9kZXNUb1NlYXJjaC5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub2RlID0gbm9kZXNUb1NlYXJjaC5wb3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIGNvbGxpZGVzOiBmdW5jdGlvbiAoYmJveCkge1xuXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5kYXRhLFxuICAgICAgICAgICAgdG9CQm94ID0gdGhpcy50b0JCb3g7XG5cbiAgICAgICAgaWYgKCFpbnRlcnNlY3RzKGJib3gsIG5vZGUpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIG5vZGVzVG9TZWFyY2ggPSBbXSxcbiAgICAgICAgICAgIGksIGxlbiwgY2hpbGQsIGNoaWxkQkJveDtcblxuICAgICAgICB3aGlsZSAobm9kZSkge1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGNoaWxkQkJveCA9IG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZDtcblxuICAgICAgICAgICAgICAgIGlmIChpbnRlcnNlY3RzKGJib3gsIGNoaWxkQkJveCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGUubGVhZiB8fCBjb250YWlucyhiYm94LCBjaGlsZEJCb3gpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZXNUb1NlYXJjaC5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub2RlID0gbm9kZXNUb1NlYXJjaC5wb3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgbG9hZDogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgaWYgKCEoZGF0YSAmJiBkYXRhLmxlbmd0aCkpIHJldHVybiB0aGlzO1xuXG4gICAgICAgIGlmIChkYXRhLmxlbmd0aCA8IHRoaXMuX21pbkVudHJpZXMpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBkYXRhLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnNlcnQoZGF0YVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlY3Vyc2l2ZWx5IGJ1aWxkIHRoZSB0cmVlIHdpdGggdGhlIGdpdmVuIGRhdGEgZnJvbSBzdHJhdGNoIHVzaW5nIE9NVCBhbGdvcml0aG1cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLl9idWlsZChkYXRhLnNsaWNlKCksIDAsIGRhdGEubGVuZ3RoIC0gMSwgMCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmRhdGEuY2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBzYXZlIGFzIGlzIGlmIHRyZWUgaXMgZW1wdHlcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5vZGU7XG5cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmRhdGEuaGVpZ2h0ID09PSBub2RlLmhlaWdodCkge1xuICAgICAgICAgICAgLy8gc3BsaXQgcm9vdCBpZiB0cmVlcyBoYXZlIHRoZSBzYW1lIGhlaWdodFxuICAgICAgICAgICAgdGhpcy5fc3BsaXRSb290KHRoaXMuZGF0YSwgbm9kZSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRhdGEuaGVpZ2h0IDwgbm9kZS5oZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAvLyBzd2FwIHRyZWVzIGlmIGluc2VydGVkIG9uZSBpcyBiaWdnZXJcbiAgICAgICAgICAgICAgICB2YXIgdG1wTm9kZSA9IHRoaXMuZGF0YTtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBub2RlO1xuICAgICAgICAgICAgICAgIG5vZGUgPSB0bXBOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpbnNlcnQgdGhlIHNtYWxsIHRyZWUgaW50byB0aGUgbGFyZ2UgdHJlZSBhdCBhcHByb3ByaWF0ZSBsZXZlbFxuICAgICAgICAgICAgdGhpcy5faW5zZXJ0KG5vZGUsIHRoaXMuZGF0YS5oZWlnaHQgLSBub2RlLmhlaWdodCAtIDEsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGluc2VydDogZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgaWYgKGl0ZW0pIHRoaXMuX2luc2VydChpdGVtLCB0aGlzLmRhdGEuaGVpZ2h0IC0gMSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBjbGVhcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRhdGEgPSBjcmVhdGVOb2RlKFtdKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHJlbW92ZTogZnVuY3Rpb24gKGl0ZW0sIGVxdWFsc0ZuKSB7XG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmRhdGEsXG4gICAgICAgICAgICBiYm94ID0gdGhpcy50b0JCb3goaXRlbSksXG4gICAgICAgICAgICBwYXRoID0gW10sXG4gICAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgICBpLCBwYXJlbnQsIGluZGV4LCBnb2luZ1VwO1xuXG4gICAgICAgIC8vIGRlcHRoLWZpcnN0IGl0ZXJhdGl2ZSB0cmVlIHRyYXZlcnNhbFxuICAgICAgICB3aGlsZSAobm9kZSB8fCBwYXRoLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIW5vZGUpIHsgLy8gZ28gdXBcbiAgICAgICAgICAgICAgICBub2RlID0gcGF0aC5wb3AoKTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgaSA9IGluZGV4ZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgZ29pbmdVcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLmxlYWYpIHsgLy8gY2hlY2sgY3VycmVudCBub2RlXG4gICAgICAgICAgICAgICAgaW5kZXggPSBmaW5kSXRlbShpdGVtLCBub2RlLmNoaWxkcmVuLCBlcXVhbHNGbik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0ZW0gZm91bmQsIHJlbW92ZSB0aGUgaXRlbSBhbmQgY29uZGVuc2UgdHJlZSB1cHdhcmRzXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25kZW5zZShwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWdvaW5nVXAgJiYgIW5vZGUubGVhZiAmJiBjb250YWlucyhub2RlLCBiYm94KSkgeyAvLyBnbyBkb3duXG4gICAgICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgIGluZGV4ZXMucHVzaChpKTtcbiAgICAgICAgICAgICAgICBpID0gMDtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBub2RlO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlLmNoaWxkcmVuWzBdO1xuXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBhcmVudCkgeyAvLyBnbyByaWdodFxuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICBub2RlID0gcGFyZW50LmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgIGdvaW5nVXAgPSBmYWxzZTtcblxuICAgICAgICAgICAgfSBlbHNlIG5vZGUgPSBudWxsOyAvLyBub3RoaW5nIGZvdW5kXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgdG9CQm94OiBmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gaXRlbTsgfSxcblxuICAgIGNvbXBhcmVNaW5YOiBjb21wYXJlTm9kZU1pblgsXG4gICAgY29tcGFyZU1pblk6IGNvbXBhcmVOb2RlTWluWSxcblxuICAgIHRvSlNPTjogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5kYXRhOyB9LFxuXG4gICAgZnJvbUpTT046IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfYWxsOiBmdW5jdGlvbiAobm9kZSwgcmVzdWx0KSB7XG4gICAgICAgIHZhciBub2Rlc1RvU2VhcmNoID0gW107XG4gICAgICAgIHdoaWxlIChub2RlKSB7XG4gICAgICAgICAgICBpZiAobm9kZS5sZWFmKSByZXN1bHQucHVzaC5hcHBseShyZXN1bHQsIG5vZGUuY2hpbGRyZW4pO1xuICAgICAgICAgICAgZWxzZSBub2Rlc1RvU2VhcmNoLnB1c2guYXBwbHkobm9kZXNUb1NlYXJjaCwgbm9kZS5jaGlsZHJlbik7XG5cbiAgICAgICAgICAgIG5vZGUgPSBub2Rlc1RvU2VhcmNoLnBvcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIF9idWlsZDogZnVuY3Rpb24gKGl0ZW1zLCBsZWZ0LCByaWdodCwgaGVpZ2h0KSB7XG5cbiAgICAgICAgdmFyIE4gPSByaWdodCAtIGxlZnQgKyAxLFxuICAgICAgICAgICAgTSA9IHRoaXMuX21heEVudHJpZXMsXG4gICAgICAgICAgICBub2RlO1xuXG4gICAgICAgIGlmIChOIDw9IE0pIHtcbiAgICAgICAgICAgIC8vIHJlYWNoZWQgbGVhZiBsZXZlbDsgcmV0dXJuIGxlYWZcbiAgICAgICAgICAgIG5vZGUgPSBjcmVhdGVOb2RlKGl0ZW1zLnNsaWNlKGxlZnQsIHJpZ2h0ICsgMSkpO1xuICAgICAgICAgICAgY2FsY0JCb3gobm9kZSwgdGhpcy50b0JCb3gpO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgLy8gdGFyZ2V0IGhlaWdodCBvZiB0aGUgYnVsay1sb2FkZWQgdHJlZVxuICAgICAgICAgICAgaGVpZ2h0ID0gTWF0aC5jZWlsKE1hdGgubG9nKE4pIC8gTWF0aC5sb2coTSkpO1xuXG4gICAgICAgICAgICAvLyB0YXJnZXQgbnVtYmVyIG9mIHJvb3QgZW50cmllcyB0byBtYXhpbWl6ZSBzdG9yYWdlIHV0aWxpemF0aW9uXG4gICAgICAgICAgICBNID0gTWF0aC5jZWlsKE4gLyBNYXRoLnBvdyhNLCBoZWlnaHQgLSAxKSk7XG4gICAgICAgIH1cblxuICAgICAgICBub2RlID0gY3JlYXRlTm9kZShbXSk7XG4gICAgICAgIG5vZGUubGVhZiA9IGZhbHNlO1xuICAgICAgICBub2RlLmhlaWdodCA9IGhlaWdodDtcblxuICAgICAgICAvLyBzcGxpdCB0aGUgaXRlbXMgaW50byBNIG1vc3RseSBzcXVhcmUgdGlsZXNcblxuICAgICAgICB2YXIgTjIgPSBNYXRoLmNlaWwoTiAvIE0pLFxuICAgICAgICAgICAgTjEgPSBOMiAqIE1hdGguY2VpbChNYXRoLnNxcnQoTSkpLFxuICAgICAgICAgICAgaSwgaiwgcmlnaHQyLCByaWdodDM7XG5cbiAgICAgICAgbXVsdGlTZWxlY3QoaXRlbXMsIGxlZnQsIHJpZ2h0LCBOMSwgdGhpcy5jb21wYXJlTWluWCk7XG5cbiAgICAgICAgZm9yIChpID0gbGVmdDsgaSA8PSByaWdodDsgaSArPSBOMSkge1xuXG4gICAgICAgICAgICByaWdodDIgPSBNYXRoLm1pbihpICsgTjEgLSAxLCByaWdodCk7XG5cbiAgICAgICAgICAgIG11bHRpU2VsZWN0KGl0ZW1zLCBpLCByaWdodDIsIE4yLCB0aGlzLmNvbXBhcmVNaW5ZKTtcblxuICAgICAgICAgICAgZm9yIChqID0gaTsgaiA8PSByaWdodDI7IGogKz0gTjIpIHtcblxuICAgICAgICAgICAgICAgIHJpZ2h0MyA9IE1hdGgubWluKGogKyBOMiAtIDEsIHJpZ2h0Mik7XG5cbiAgICAgICAgICAgICAgICAvLyBwYWNrIGVhY2ggZW50cnkgcmVjdXJzaXZlbHlcbiAgICAgICAgICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2godGhpcy5fYnVpbGQoaXRlbXMsIGosIHJpZ2h0MywgaGVpZ2h0IC0gMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY2FsY0JCb3gobm9kZSwgdGhpcy50b0JCb3gpO1xuXG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH0sXG5cbiAgICBfY2hvb3NlU3VidHJlZTogZnVuY3Rpb24gKGJib3gsIG5vZGUsIGxldmVsLCBwYXRoKSB7XG5cbiAgICAgICAgdmFyIGksIGxlbiwgY2hpbGQsIHRhcmdldE5vZGUsIGFyZWEsIGVubGFyZ2VtZW50LCBtaW5BcmVhLCBtaW5FbmxhcmdlbWVudDtcblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgcGF0aC5wdXNoKG5vZGUpO1xuXG4gICAgICAgICAgICBpZiAobm9kZS5sZWFmIHx8IHBhdGgubGVuZ3RoIC0gMSA9PT0gbGV2ZWwpIGJyZWFrO1xuXG4gICAgICAgICAgICBtaW5BcmVhID0gbWluRW5sYXJnZW1lbnQgPSBJbmZpbml0eTtcblxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGNoaWxkID0gbm9kZS5jaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICBhcmVhID0gYmJveEFyZWEoY2hpbGQpO1xuICAgICAgICAgICAgICAgIGVubGFyZ2VtZW50ID0gZW5sYXJnZWRBcmVhKGJib3gsIGNoaWxkKSAtIGFyZWE7XG5cbiAgICAgICAgICAgICAgICAvLyBjaG9vc2UgZW50cnkgd2l0aCB0aGUgbGVhc3QgYXJlYSBlbmxhcmdlbWVudFxuICAgICAgICAgICAgICAgIGlmIChlbmxhcmdlbWVudCA8IG1pbkVubGFyZ2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkVubGFyZ2VtZW50ID0gZW5sYXJnZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIG1pbkFyZWEgPSBhcmVhIDwgbWluQXJlYSA/IGFyZWEgOiBtaW5BcmVhO1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVubGFyZ2VtZW50ID09PSBtaW5FbmxhcmdlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgY2hvb3NlIG9uZSB3aXRoIHRoZSBzbWFsbGVzdCBhcmVhXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmVhIDwgbWluQXJlYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlID0gY2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vZGUgPSB0YXJnZXROb2RlIHx8IG5vZGUuY2hpbGRyZW5bMF07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICB9LFxuXG4gICAgX2luc2VydDogZnVuY3Rpb24gKGl0ZW0sIGxldmVsLCBpc05vZGUpIHtcblxuICAgICAgICB2YXIgdG9CQm94ID0gdGhpcy50b0JCb3gsXG4gICAgICAgICAgICBiYm94ID0gaXNOb2RlID8gaXRlbSA6IHRvQkJveChpdGVtKSxcbiAgICAgICAgICAgIGluc2VydFBhdGggPSBbXTtcblxuICAgICAgICAvLyBmaW5kIHRoZSBiZXN0IG5vZGUgZm9yIGFjY29tbW9kYXRpbmcgdGhlIGl0ZW0sIHNhdmluZyBhbGwgbm9kZXMgYWxvbmcgdGhlIHBhdGggdG9vXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fY2hvb3NlU3VidHJlZShiYm94LCB0aGlzLmRhdGEsIGxldmVsLCBpbnNlcnRQYXRoKTtcblxuICAgICAgICAvLyBwdXQgdGhlIGl0ZW0gaW50byB0aGUgbm9kZVxuICAgICAgICBub2RlLmNoaWxkcmVuLnB1c2goaXRlbSk7XG4gICAgICAgIGV4dGVuZChub2RlLCBiYm94KTtcblxuICAgICAgICAvLyBzcGxpdCBvbiBub2RlIG92ZXJmbG93OyBwcm9wYWdhdGUgdXB3YXJkcyBpZiBuZWNlc3NhcnlcbiAgICAgICAgd2hpbGUgKGxldmVsID49IDApIHtcbiAgICAgICAgICAgIGlmIChpbnNlcnRQYXRoW2xldmVsXS5jaGlsZHJlbi5sZW5ndGggPiB0aGlzLl9tYXhFbnRyaWVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3BsaXQoaW5zZXJ0UGF0aCwgbGV2ZWwpO1xuICAgICAgICAgICAgICAgIGxldmVsLS07XG4gICAgICAgICAgICB9IGVsc2UgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBpbnNlcnRpb24gcGF0aFxuICAgICAgICB0aGlzLl9hZGp1c3RQYXJlbnRCQm94ZXMoYmJveCwgaW5zZXJ0UGF0aCwgbGV2ZWwpO1xuICAgIH0sXG5cbiAgICAvLyBzcGxpdCBvdmVyZmxvd2VkIG5vZGUgaW50byB0d29cbiAgICBfc3BsaXQ6IGZ1bmN0aW9uIChpbnNlcnRQYXRoLCBsZXZlbCkge1xuXG4gICAgICAgIHZhciBub2RlID0gaW5zZXJ0UGF0aFtsZXZlbF0sXG4gICAgICAgICAgICBNID0gbm9kZS5jaGlsZHJlbi5sZW5ndGgsXG4gICAgICAgICAgICBtID0gdGhpcy5fbWluRW50cmllcztcblxuICAgICAgICB0aGlzLl9jaG9vc2VTcGxpdEF4aXMobm9kZSwgbSwgTSk7XG5cbiAgICAgICAgdmFyIHNwbGl0SW5kZXggPSB0aGlzLl9jaG9vc2VTcGxpdEluZGV4KG5vZGUsIG0sIE0pO1xuXG4gICAgICAgIHZhciBuZXdOb2RlID0gY3JlYXRlTm9kZShub2RlLmNoaWxkcmVuLnNwbGljZShzcGxpdEluZGV4LCBub2RlLmNoaWxkcmVuLmxlbmd0aCAtIHNwbGl0SW5kZXgpKTtcbiAgICAgICAgbmV3Tm9kZS5oZWlnaHQgPSBub2RlLmhlaWdodDtcbiAgICAgICAgbmV3Tm9kZS5sZWFmID0gbm9kZS5sZWFmO1xuXG4gICAgICAgIGNhbGNCQm94KG5vZGUsIHRoaXMudG9CQm94KTtcbiAgICAgICAgY2FsY0JCb3gobmV3Tm9kZSwgdGhpcy50b0JCb3gpO1xuXG4gICAgICAgIGlmIChsZXZlbCkgaW5zZXJ0UGF0aFtsZXZlbCAtIDFdLmNoaWxkcmVuLnB1c2gobmV3Tm9kZSk7XG4gICAgICAgIGVsc2UgdGhpcy5fc3BsaXRSb290KG5vZGUsIG5ld05vZGUpO1xuICAgIH0sXG5cbiAgICBfc3BsaXRSb290OiBmdW5jdGlvbiAobm9kZSwgbmV3Tm9kZSkge1xuICAgICAgICAvLyBzcGxpdCByb290IG5vZGVcbiAgICAgICAgdGhpcy5kYXRhID0gY3JlYXRlTm9kZShbbm9kZSwgbmV3Tm9kZV0pO1xuICAgICAgICB0aGlzLmRhdGEuaGVpZ2h0ID0gbm9kZS5oZWlnaHQgKyAxO1xuICAgICAgICB0aGlzLmRhdGEubGVhZiA9IGZhbHNlO1xuICAgICAgICBjYWxjQkJveCh0aGlzLmRhdGEsIHRoaXMudG9CQm94KTtcbiAgICB9LFxuXG4gICAgX2Nob29zZVNwbGl0SW5kZXg6IGZ1bmN0aW9uIChub2RlLCBtLCBNKSB7XG5cbiAgICAgICAgdmFyIGksIGJib3gxLCBiYm94Miwgb3ZlcmxhcCwgYXJlYSwgbWluT3ZlcmxhcCwgbWluQXJlYSwgaW5kZXg7XG5cbiAgICAgICAgbWluT3ZlcmxhcCA9IG1pbkFyZWEgPSBJbmZpbml0eTtcblxuICAgICAgICBmb3IgKGkgPSBtOyBpIDw9IE0gLSBtOyBpKyspIHtcbiAgICAgICAgICAgIGJib3gxID0gZGlzdEJCb3gobm9kZSwgMCwgaSwgdGhpcy50b0JCb3gpO1xuICAgICAgICAgICAgYmJveDIgPSBkaXN0QkJveChub2RlLCBpLCBNLCB0aGlzLnRvQkJveCk7XG5cbiAgICAgICAgICAgIG92ZXJsYXAgPSBpbnRlcnNlY3Rpb25BcmVhKGJib3gxLCBiYm94Mik7XG4gICAgICAgICAgICBhcmVhID0gYmJveEFyZWEoYmJveDEpICsgYmJveEFyZWEoYmJveDIpO1xuXG4gICAgICAgICAgICAvLyBjaG9vc2UgZGlzdHJpYnV0aW9uIHdpdGggbWluaW11bSBvdmVybGFwXG4gICAgICAgICAgICBpZiAob3ZlcmxhcCA8IG1pbk92ZXJsYXApIHtcbiAgICAgICAgICAgICAgICBtaW5PdmVybGFwID0gb3ZlcmxhcDtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGk7XG5cbiAgICAgICAgICAgICAgICBtaW5BcmVhID0gYXJlYSA8IG1pbkFyZWEgPyBhcmVhIDogbWluQXJlYTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmIChvdmVybGFwID09PSBtaW5PdmVybGFwKSB7XG4gICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGNob29zZSBkaXN0cmlidXRpb24gd2l0aCBtaW5pbXVtIGFyZWFcbiAgICAgICAgICAgICAgICBpZiAoYXJlYSA8IG1pbkFyZWEpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluQXJlYSA9IGFyZWE7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgfSxcblxuICAgIC8vIHNvcnRzIG5vZGUgY2hpbGRyZW4gYnkgdGhlIGJlc3QgYXhpcyBmb3Igc3BsaXRcbiAgICBfY2hvb3NlU3BsaXRBeGlzOiBmdW5jdGlvbiAobm9kZSwgbSwgTSkge1xuXG4gICAgICAgIHZhciBjb21wYXJlTWluWCA9IG5vZGUubGVhZiA/IHRoaXMuY29tcGFyZU1pblggOiBjb21wYXJlTm9kZU1pblgsXG4gICAgICAgICAgICBjb21wYXJlTWluWSA9IG5vZGUubGVhZiA/IHRoaXMuY29tcGFyZU1pblkgOiBjb21wYXJlTm9kZU1pblksXG4gICAgICAgICAgICB4TWFyZ2luID0gdGhpcy5fYWxsRGlzdE1hcmdpbihub2RlLCBtLCBNLCBjb21wYXJlTWluWCksXG4gICAgICAgICAgICB5TWFyZ2luID0gdGhpcy5fYWxsRGlzdE1hcmdpbihub2RlLCBtLCBNLCBjb21wYXJlTWluWSk7XG5cbiAgICAgICAgLy8gaWYgdG90YWwgZGlzdHJpYnV0aW9ucyBtYXJnaW4gdmFsdWUgaXMgbWluaW1hbCBmb3IgeCwgc29ydCBieSBtaW5YLFxuICAgICAgICAvLyBvdGhlcndpc2UgaXQncyBhbHJlYWR5IHNvcnRlZCBieSBtaW5ZXG4gICAgICAgIGlmICh4TWFyZ2luIDwgeU1hcmdpbikgbm9kZS5jaGlsZHJlbi5zb3J0KGNvbXBhcmVNaW5YKTtcbiAgICB9LFxuXG4gICAgLy8gdG90YWwgbWFyZ2luIG9mIGFsbCBwb3NzaWJsZSBzcGxpdCBkaXN0cmlidXRpb25zIHdoZXJlIGVhY2ggbm9kZSBpcyBhdCBsZWFzdCBtIGZ1bGxcbiAgICBfYWxsRGlzdE1hcmdpbjogZnVuY3Rpb24gKG5vZGUsIG0sIE0sIGNvbXBhcmUpIHtcblxuICAgICAgICBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZSk7XG5cbiAgICAgICAgdmFyIHRvQkJveCA9IHRoaXMudG9CQm94LFxuICAgICAgICAgICAgbGVmdEJCb3ggPSBkaXN0QkJveChub2RlLCAwLCBtLCB0b0JCb3gpLFxuICAgICAgICAgICAgcmlnaHRCQm94ID0gZGlzdEJCb3gobm9kZSwgTSAtIG0sIE0sIHRvQkJveCksXG4gICAgICAgICAgICBtYXJnaW4gPSBiYm94TWFyZ2luKGxlZnRCQm94KSArIGJib3hNYXJnaW4ocmlnaHRCQm94KSxcbiAgICAgICAgICAgIGksIGNoaWxkO1xuXG4gICAgICAgIGZvciAoaSA9IG07IGkgPCBNIC0gbTsgaSsrKSB7XG4gICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICBleHRlbmQobGVmdEJCb3gsIG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZCk7XG4gICAgICAgICAgICBtYXJnaW4gKz0gYmJveE1hcmdpbihsZWZ0QkJveCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSBNIC0gbSAtIDE7IGkgPj0gbTsgaS0tKSB7XG4gICAgICAgICAgICBjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV07XG4gICAgICAgICAgICBleHRlbmQocmlnaHRCQm94LCBub2RlLmxlYWYgPyB0b0JCb3goY2hpbGQpIDogY2hpbGQpO1xuICAgICAgICAgICAgbWFyZ2luICs9IGJib3hNYXJnaW4ocmlnaHRCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXJnaW47XG4gICAgfSxcblxuICAgIF9hZGp1c3RQYXJlbnRCQm94ZXM6IGZ1bmN0aW9uIChiYm94LCBwYXRoLCBsZXZlbCkge1xuICAgICAgICAvLyBhZGp1c3QgYmJveGVzIGFsb25nIHRoZSBnaXZlbiB0cmVlIHBhdGhcbiAgICAgICAgZm9yICh2YXIgaSA9IGxldmVsOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgZXh0ZW5kKHBhdGhbaV0sIGJib3gpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9jb25kZW5zZTogZnVuY3Rpb24gKHBhdGgpIHtcbiAgICAgICAgLy8gZ28gdGhyb3VnaCB0aGUgcGF0aCwgcmVtb3ZpbmcgZW1wdHkgbm9kZXMgYW5kIHVwZGF0aW5nIGJib3hlc1xuICAgICAgICBmb3IgKHZhciBpID0gcGF0aC5sZW5ndGggLSAxLCBzaWJsaW5nczsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGlmIChwYXRoW2ldLmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBzaWJsaW5ncyA9IHBhdGhbaSAtIDFdLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICBzaWJsaW5ncy5zcGxpY2Uoc2libGluZ3MuaW5kZXhPZihwYXRoW2ldKSwgMSk7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgdGhpcy5jbGVhcigpO1xuXG4gICAgICAgICAgICB9IGVsc2UgY2FsY0JCb3gocGF0aFtpXSwgdGhpcy50b0JCb3gpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIF9pbml0Rm9ybWF0OiBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgIC8vIGRhdGEgZm9ybWF0IChtaW5YLCBtaW5ZLCBtYXhYLCBtYXhZIGFjY2Vzc29ycylcblxuICAgICAgICAvLyB1c2VzIGV2YWwtdHlwZSBmdW5jdGlvbiBjb21waWxhdGlvbiBpbnN0ZWFkIG9mIGp1c3QgYWNjZXB0aW5nIGEgdG9CQm94IGZ1bmN0aW9uXG4gICAgICAgIC8vIGJlY2F1c2UgdGhlIGFsZ29yaXRobXMgYXJlIHZlcnkgc2Vuc2l0aXZlIHRvIHNvcnRpbmcgZnVuY3Rpb25zIHBlcmZvcm1hbmNlLFxuICAgICAgICAvLyBzbyB0aGV5IHNob3VsZCBiZSBkZWFkIHNpbXBsZSBhbmQgd2l0aG91dCBpbm5lciBjYWxsc1xuXG4gICAgICAgIHZhciBjb21wYXJlQXJyID0gWydyZXR1cm4gYScsICcgLSBiJywgJzsnXTtcblxuICAgICAgICB0aGlzLmNvbXBhcmVNaW5YID0gbmV3IEZ1bmN0aW9uKCdhJywgJ2InLCBjb21wYXJlQXJyLmpvaW4oZm9ybWF0WzBdKSk7XG4gICAgICAgIHRoaXMuY29tcGFyZU1pblkgPSBuZXcgRnVuY3Rpb24oJ2EnLCAnYicsIGNvbXBhcmVBcnIuam9pbihmb3JtYXRbMV0pKTtcblxuICAgICAgICB0aGlzLnRvQkJveCA9IG5ldyBGdW5jdGlvbignYScsXG4gICAgICAgICAgICAncmV0dXJuIHttaW5YOiBhJyArIGZvcm1hdFswXSArXG4gICAgICAgICAgICAnLCBtaW5ZOiBhJyArIGZvcm1hdFsxXSArXG4gICAgICAgICAgICAnLCBtYXhYOiBhJyArIGZvcm1hdFsyXSArXG4gICAgICAgICAgICAnLCBtYXhZOiBhJyArIGZvcm1hdFszXSArICd9OycpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGZpbmRJdGVtKGl0ZW0sIGl0ZW1zLCBlcXVhbHNGbikge1xuICAgIGlmICghZXF1YWxzRm4pIHJldHVybiBpdGVtcy5pbmRleE9mKGl0ZW0pO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZXF1YWxzRm4oaXRlbSwgaXRlbXNbaV0pKSByZXR1cm4gaTtcbiAgICB9XG4gICAgcmV0dXJuIC0xO1xufVxuXG4vLyBjYWxjdWxhdGUgbm9kZSdzIGJib3ggZnJvbSBiYm94ZXMgb2YgaXRzIGNoaWxkcmVuXG5mdW5jdGlvbiBjYWxjQkJveChub2RlLCB0b0JCb3gpIHtcbiAgICBkaXN0QkJveChub2RlLCAwLCBub2RlLmNoaWxkcmVuLmxlbmd0aCwgdG9CQm94LCBub2RlKTtcbn1cblxuLy8gbWluIGJvdW5kaW5nIHJlY3RhbmdsZSBvZiBub2RlIGNoaWxkcmVuIGZyb20gayB0byBwLTFcbmZ1bmN0aW9uIGRpc3RCQm94KG5vZGUsIGssIHAsIHRvQkJveCwgZGVzdE5vZGUpIHtcbiAgICBpZiAoIWRlc3ROb2RlKSBkZXN0Tm9kZSA9IGNyZWF0ZU5vZGUobnVsbCk7XG4gICAgZGVzdE5vZGUubWluWCA9IEluZmluaXR5O1xuICAgIGRlc3ROb2RlLm1pblkgPSBJbmZpbml0eTtcbiAgICBkZXN0Tm9kZS5tYXhYID0gLUluZmluaXR5O1xuICAgIGRlc3ROb2RlLm1heFkgPSAtSW5maW5pdHk7XG5cbiAgICBmb3IgKHZhciBpID0gaywgY2hpbGQ7IGkgPCBwOyBpKyspIHtcbiAgICAgICAgY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICBleHRlbmQoZGVzdE5vZGUsIG5vZGUubGVhZiA/IHRvQkJveChjaGlsZCkgOiBjaGlsZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlc3ROb2RlO1xufVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGEubWluWCA9IE1hdGgubWluKGEubWluWCwgYi5taW5YKTtcbiAgICBhLm1pblkgPSBNYXRoLm1pbihhLm1pblksIGIubWluWSk7XG4gICAgYS5tYXhYID0gTWF0aC5tYXgoYS5tYXhYLCBiLm1heFgpO1xuICAgIGEubWF4WSA9IE1hdGgubWF4KGEubWF4WSwgYi5tYXhZKTtcbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5YKGEsIGIpIHsgcmV0dXJuIGEubWluWCAtIGIubWluWDsgfVxuZnVuY3Rpb24gY29tcGFyZU5vZGVNaW5ZKGEsIGIpIHsgcmV0dXJuIGEubWluWSAtIGIubWluWTsgfVxuXG5mdW5jdGlvbiBiYm94QXJlYShhKSAgIHsgcmV0dXJuIChhLm1heFggLSBhLm1pblgpICogKGEubWF4WSAtIGEubWluWSk7IH1cbmZ1bmN0aW9uIGJib3hNYXJnaW4oYSkgeyByZXR1cm4gKGEubWF4WCAtIGEubWluWCkgKyAoYS5tYXhZIC0gYS5taW5ZKTsgfVxuXG5mdW5jdGlvbiBlbmxhcmdlZEFyZWEoYSwgYikge1xuICAgIHJldHVybiAoTWF0aC5tYXgoYi5tYXhYLCBhLm1heFgpIC0gTWF0aC5taW4oYi5taW5YLCBhLm1pblgpKSAqXG4gICAgICAgICAgIChNYXRoLm1heChiLm1heFksIGEubWF4WSkgLSBNYXRoLm1pbihiLm1pblksIGEubWluWSkpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb25BcmVhKGEsIGIpIHtcbiAgICB2YXIgbWluWCA9IE1hdGgubWF4KGEubWluWCwgYi5taW5YKSxcbiAgICAgICAgbWluWSA9IE1hdGgubWF4KGEubWluWSwgYi5taW5ZKSxcbiAgICAgICAgbWF4WCA9IE1hdGgubWluKGEubWF4WCwgYi5tYXhYKSxcbiAgICAgICAgbWF4WSA9IE1hdGgubWluKGEubWF4WSwgYi5tYXhZKTtcblxuICAgIHJldHVybiBNYXRoLm1heCgwLCBtYXhYIC0gbWluWCkgKlxuICAgICAgICAgICBNYXRoLm1heCgwLCBtYXhZIC0gbWluWSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGEsIGIpIHtcbiAgICByZXR1cm4gYS5taW5YIDw9IGIubWluWCAmJlxuICAgICAgICAgICBhLm1pblkgPD0gYi5taW5ZICYmXG4gICAgICAgICAgIGIubWF4WCA8PSBhLm1heFggJiZcbiAgICAgICAgICAgYi5tYXhZIDw9IGEubWF4WTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0cyhhLCBiKSB7XG4gICAgcmV0dXJuIGIubWluWCA8PSBhLm1heFggJiZcbiAgICAgICAgICAgYi5taW5ZIDw9IGEubWF4WSAmJlxuICAgICAgICAgICBiLm1heFggPj0gYS5taW5YICYmXG4gICAgICAgICAgIGIubWF4WSA+PSBhLm1pblk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU5vZGUoY2hpbGRyZW4pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBjaGlsZHJlbjogY2hpbGRyZW4sXG4gICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgbGVhZjogdHJ1ZSxcbiAgICAgICAgbWluWDogSW5maW5pdHksXG4gICAgICAgIG1pblk6IEluZmluaXR5LFxuICAgICAgICBtYXhYOiAtSW5maW5pdHksXG4gICAgICAgIG1heFk6IC1JbmZpbml0eVxuICAgIH07XG59XG5cbi8vIHNvcnQgYW4gYXJyYXkgc28gdGhhdCBpdGVtcyBjb21lIGluIGdyb3VwcyBvZiBuIHVuc29ydGVkIGl0ZW1zLCB3aXRoIGdyb3VwcyBzb3J0ZWQgYmV0d2VlbiBlYWNoIG90aGVyO1xuLy8gY29tYmluZXMgc2VsZWN0aW9uIGFsZ29yaXRobSB3aXRoIGJpbmFyeSBkaXZpZGUgJiBjb25xdWVyIGFwcHJvYWNoXG5cbmZ1bmN0aW9uIG11bHRpU2VsZWN0KGFyciwgbGVmdCwgcmlnaHQsIG4sIGNvbXBhcmUpIHtcbiAgICB2YXIgc3RhY2sgPSBbbGVmdCwgcmlnaHRdLFxuICAgICAgICBtaWQ7XG5cbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoKSB7XG4gICAgICAgIHJpZ2h0ID0gc3RhY2sucG9wKCk7XG4gICAgICAgIGxlZnQgPSBzdGFjay5wb3AoKTtcblxuICAgICAgICBpZiAocmlnaHQgLSBsZWZ0IDw9IG4pIGNvbnRpbnVlO1xuXG4gICAgICAgIG1pZCA9IGxlZnQgKyBNYXRoLmNlaWwoKHJpZ2h0IC0gbGVmdCkgLyBuIC8gMikgKiBuO1xuICAgICAgICBxdWlja3NlbGVjdChhcnIsIG1pZCwgbGVmdCwgcmlnaHQsIGNvbXBhcmUpO1xuXG4gICAgICAgIHN0YWNrLnB1c2gobGVmdCwgbWlkLCBtaWQsIHJpZ2h0KTtcbiAgICB9XG59XG4iXX0=
require=(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})({"e2d":[function(require,module,exports){
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["e2d"] = factory();
else
root["e2d"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 58);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {
class Instruction {
constructor(type, props) {
this.type = type;
this.props = props;
return Object.seal(this);
}
}
Object.seal(Instruction);
Object.seal(Instruction.prototype);
module.exports = Instruction;
/***/ },
/* 1 */
/***/ function(module, exports) {
let transformPoints = (points, matrix) => {
let result = [],
x, y;
for(let i = 0; i < points.length; i++) {
[x, y] = points[i];
result.push([
matrix[0] * x + matrix[2] * y + matrix[4],
matrix[1] * x + matrix[3] * y + matrix[5]
]);
}
return result;
};
module.exports = transformPoints;
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0),
cache = new Instruction('beginPath');
let beginPath = () => cache;
module.exports = beginPath;
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let cache = new Instruction('closePath');
let closePath = () => cache;
module.exports = closePath;
/***/ },
/* 4 */
/***/ function(module, exports) {
let cycleMouseData = (ctx) => {
let mouseData = ctx.canvas[Symbol.for('mouseData')];
if (mouseData) {
mouseData.dx = mouseData.x - mouseData.previousX;
mouseData.dy = mouseData.y - mouseData.previousY;
mouseData.previousX = mouseData.x;
mouseData.previousY = mouseData.y;
mouseData.clicked = 0;
}
};
module.exports = cycleMouseData;
/***/ },
/* 5 */
/***/ function(module, exports) {
let det = 0;
let invertMatrix = ([a, b, c, d, e, f]) => (
det = 1 / (a * d - c * b),
[
d * det,
-c * det,
-b * det,
a * det,
(b * f - e * d) * det,
(e * b - a * f) * det
]
);
module.exports = invertMatrix;
/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let lineTo = (x, y) => new Instruction('lineTo', { x, y });
module.exports = lineTo;
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let moveTo = (x, y) => new Instruction('moveTo', { x, y });
module.exports = moveTo;
/***/ },
/* 8 */
/***/ function(module, exports) {
let pointInRect = ([px, py], [[x, y], [width, height]]) => px > x && py > y && px < width && py < height;
module.exports = pointInRect;
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let setTransform = (matrix, ...children) => [
new Instruction('setTransform', [
matrix[0],
matrix[1],
matrix[2],
matrix[3],
matrix[4],
matrix[5]
]),
children,
end
];
module.exports = setTransform;
/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {
let pointInPolygon = __webpack_require__(57);
let transformPoints = __webpack_require__(1);
let invertMatrix = __webpack_require__(5);
let pointInRect = __webpack_require__(8);
let matrix = new Float64Array(6);
module.exports = (ctx) => {
let regions = ctx.canvas[Symbol.for('regions')],
mousePoints = ctx.canvas[Symbol.for('mousePoints')],
mouseData = ctx.canvas[Symbol.for('mouseData')],
results = {};
//the mouse might have held still, add the current mouse position
if (mousePoints.length === 0) {
mousePoints.push([mouseData.x, mouseData.y, mouseData.state]);
}
for(let region of regions) {
//invert the region matrix and transform the mouse points
let transformedMousePoints = transformPoints(mousePoints, invertMatrix(region.matrix));
//the mouse points are now relative to the mouse region
if (!region.polygon) {
for (let mousePoint of transformedMousePoints) {
if (pointInRect(mousePoint, region.points)) {
region.hover = true;
region.clicked = !!mouseData.clicked;
results[region.id] = region;
break;
}
}
continue;
}
//loop over each point until one is matched
for(let mousePoint of transformedMousePoints) {
if (pointInPolygon(mousePoint, region.points)) {
region.hover = true;
region.clicked = !!mouseData.clicked;
results[region.id] = region;
break;
}
}
}
return results;
};
/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0),
pi2 = Math.PI * 2;
let arc = (...args) => {
let [x, y, r, startAngle, endAngle, counterclockwise] = args;
let props = { x: 0, y: 0, r: x, startAngle: 0, endAngle: pi2, counterclockwise: false };
if (args.length > 3) {
props.startAngle = startAngle;
props.endAngle = endAngle;
props.counterclockwise = !!counterclockwise;
}
if (args.length > 1){
props.x = x;
props.y = y;
props.r = r;
}
return new Instruction("arc", props);
};
module.exports = arc;
/***/ },
/* 12 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let arcTo = (x1, y1, x2, y2, r) => new Instruction('arcTo', { x1, y1, x2, y2, r });
module.exports = arcTo;
/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let bezierCurveTo = (cp1x, cp1y, cp2x, cp2y, x, y) => new Instruction('bezierCurveTo', {
cp1x,
cp1y,
cp2x,
cp2y,
x,
y
});
module.exports = bezierCurveTo;
/***/ },
/* 14 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let clearRect = (...args) => new Instruction('clearRect',
args.length > 2 ?
{ x: args[0], y: args[1], width: args[2], height: args[3] } :
{ x: 0, y: 0, width: args[0], height: args[1] }
);
module.exports = clearRect;
/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let begin = new Instruction('beginClip'),
performClip = new Instruction('clip'),
end = new Instruction('endClip');
let clip = (path, ...children) => [
begin,
path,
performClip,
children,
end
];
module.exports = clip;
/***/ },
/* 16 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let cache = new Instruction('clipPath');
let clipPath = () => cache;
module.exports = clipPath;
/***/ },
/* 17 */
/***/ function(module, exports) {
let createRegularPolygon = (radius = 0, position = [0, 0], sides = 3) => {
let polygon = [];
for(let i = 0; i < sides; i++) {
polygon.push([
position[0] + radius * Math.cos(Math.PI * 2 * i / sides),
position[1] + radius * Math.sin(Math.PI * 2 * i / sides)
]);
}
return polygon;
};
module.exports = createRegularPolygon;
/***/ },
/* 18 */
/***/ function(module, exports) {
let concat = [].concat;
let createWrapper = (...args) => {
for(let i = 0; i < args.length; i++) {
//parse and flatten the arguments
while (args[i] && args[i].constructor === Array) {
args = concat.apply([], args).filter(Boolean);
}
if (!args[i]) {
continue;
}
let { type } = args[i];
if (type === 'placeholder') {
// i is set to the placeholder index now
//now grab all the elements to the left of the placeHolder
let left = args.splice(0, i);
//remove the placeHolder from the array
args.shift();
return (...children) => [left, children, args];
}
}
throw new Error('Could not find placeholder, did you forget the e2d.placeHolder() call?');
};
module.exports = concat;
/***/ },
/* 19 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let drawImage = (...args) => {
let [img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight] = args;
if (args.length === 9) {
return new Instruction('drawImageSource', {
img,
sx,
sy,
sWidth,
sHeight,
dx,
dy,
dWidth,
dHeight
});
}
if (args.length >= 5) {
return new Instruction('drawImageSize', {
img,
dx: sx,
dy: sy,
dWidth: sWidth,
dHeight: sHeight
});
}
if (args.length >= 3) {
return new Instruction('drawImage', {
img,
dx: sx,
dy: sy
});
}
return new Instruction('drawImage', {
img,
dx: 0,
dy: 0
});
};
module.exports = drawImage;
/***/ },
/* 20 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0),
pi2 = Math.PI * 2;
let ellipse = (...args) => {
let [x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise] = args;
let props = { x: 0, y: 0, radiusX: x, radiusY: y, rotation: 0, startAngle: 0, endAngle: pi2, anticlockwise: false };
if (args.length > 5) {
props.startAngle = startAngle;
props.endAngle = endAngle;
props.anticlockwise = !!anticlockwise;
}
if (args.length > 4) {
props.rotation = rotation;
}
if (args.length > 2){
props.x = x;
props.y = y;
props.radiusX = radiusX;
props.radiusY = radiusY;
}
return new Instruction("ellipse", props);
};
module.exports = ellipse;
/***/ },
/* 21 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let cache = new Instruction('fill');
let fill = () => cache;
module.exports = fill;
/***/ },
/* 22 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0),
pi2 = Math.PI * 2;
let fillArc = (...args) => {
let [x, y, r, startAngle, endAngle, counterclockwise] = args;
let props = { x: 0, y: 0, r: x, startAngle: 0, endAngle: pi2, counterclockwise: false };
if (args.length > 3) {
props.startAngle = startAngle;
props.endAngle = endAngle;
props.counterclockwise = !!counterclockwise;
}
if (args.length >= 2) {
props.x = x;
props.y = y;
props.r = r;
}
return new Instruction("fillArc", props);
};
module.exports = fillArc;
/***/ },
/* 23 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let fillRect = (...args) => new Instruction('fillRect',
args.length > 2 ?
{ x: args[0], y: args[1], width: args[2], height: args[3] } :
{ x: 0, y: 0, width: args[0], height: args[1] }
);
module.exports = fillRect;
/***/ },
/* 24 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endFillStyle');
let fillStyle = (value, ...children) => [
new Instruction('fillStyle', { value }),
children,
end
];
module.exports = fillStyle;
/***/ },
/* 25 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let fillText = (...args) => {
let [text, x, y, maxWidth] = args;
if (args.length < 4) {
maxWidth = null;
}
if (args.length < 3) {
x = 0;
y = 0;
}
return new Instruction('fillText', { text, x, y, maxWidth });
};
module.exports = fillText;
/***/ },
/* 26 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endGlobalAlpha');
let globalAlpha = (value, ...children) => [
new Instruction('globalAlpha', { value }),
children,
end
];
module.exports = globalAlpha;
/***/ },
/* 27 */
/***/ function(module, exports, __webpack_require__) {
var Instruction = __webpack_require__(0);
let end = new Instruction('endGlobalCompositeOperation');
let globalCompositeOperation = (value, ...children) => [
new Instruction('globalCompositeOperation', { value }),
children,
end
];
module.exports = globalCompositeOperation;
/***/ },
/* 28 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let hitRect = (id, ...args) => {
let [x, y, width, height] = args;
if (args.length <= 3) {
width = x;
height = y;
x = 0;
y = 0;
}
return new Instruction('hitRect', {
id,
points: [
[x, y],
[x + width, y + height]
]
});
};
module.exports = hitRect;
/***/ },
/* 29 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let hitRegion = (id, points) => new Instruction('hitRegion', { id, points });
module.exports = hitRegion;
/***/ },
/* 30 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endImageSmoothingEnabled');
let imageSmoothingEnabled = (value, ...children) => [
new Instruction('imageSmoothingEnabled', { value }),
children,
end
];
module.exports = imageSmoothingEnabled;
/***/ },
/* 31 */
/***/ function(module, exports, __webpack_require__) {
let keycode = __webpack_require__(56);
module.exports = (ctx) => {
let { canvas } = ctx;
//mouseData
canvas[Symbol.for('mouseData')] = {
x: 0,
y: 0,
dx: 0,
dy: 0,
previousX: 0,
previousY: 0,
state: false,
clicked: 0
};
let keys = canvas[Symbol.for('keyData')] = {};
for (let name in keycode.code) {
if (keycode.code.hasOwnProperty(name)) {
keys[name] = false;
}
}
//mouse regions
canvas[Symbol.for('regions')] = [];
canvas[Symbol.for('mousePoints')] = [];
//make the canvas receive touch and mouse events
canvas.tabIndex = 1;
let mouseMove = (evt) => {
let { clientX, clientY } = evt;
//get left and top coordinates
let { left, top } = canvas.getBoundingClientRect();
let mouseData = canvas[Symbol.for('mouseData')];
let point = [clientX - left, clientY - top, mouseData.state];
mouseData.x = point[0];
mouseData.y = point[1];
let points = canvas[Symbol.for('mousePoints')];
points.push(point);
//store the last 100 stored positions for hover detection
if (points.length > 100) {
points.splice(0, points.length - 100);
}
evt.preventDefault();
return false;
};
canvas.addEventListener('mousemove', (evt) => mouseMove(evt));
canvas.addEventListener('mousedown', (evt) => {
let { target } = evt;
if (target === canvas) {
let mouseData = canvas[Symbol.for('mouseData')];
if (!mouseData.state) {
mouseData.clicked += 1;
}
mouseData.state = true;
return mouseMove(evt);
}
});
canvas.addEventListener('mouseup', (evt) => {
let mouseData = canvas[Symbol.for('mouseData')];
mouseData.state = false;
return mouseMove(evt);
});
canvas.addEventListener('keydown', (evt) => {
canvas[Symbol.for('keyData')][keycode(evt.keyCode)] = true;
evt.preventDefault();
return false;
});
canvas.addEventListener('keyup', (evt) => {
canvas[Symbol.for('keyData')][keycode(evt.keyCode)] = false;
evt.preventDefault();
return false;
});
};
/***/ },
/* 32 */
/***/ function(module, exports) {
module.exports = (ctx) => ctx.canvas[Symbol.for('keyData')];
/***/ },
/* 33 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endLineStyle');
let lineStyle = (value, ...children) => {
value = value || {};
var result = {
lineWidth: null,
lineCap: null,
lineJoin: null,
miterLimit: null,
lineDash: null,
lineDashOffset: null
};
if (typeof value.lineWidth !== 'undefined') {
result.lineWidth = value.lineWidth;
}
if (typeof value.lineCap !== 'undefined') {
result.lineCap = value.lineCap;
}
if (typeof value.lineJoin !== 'undefined') {
result.lineJoin = value.lineJoin;
}
if (typeof value.miterLimit !== 'undefined') {
result.miterLimit = value.miterLimit;
}
if (typeof value.lineDash !== 'undefined') {
result.lineDash = value.lineDash || [];
}
if (typeof value.lineDashOffset !== 'undefined') {
result.lineDashOffset = value.lineDashOffset;
}
return [
new Instruction('lineStyle', result),
children,
end
];
};
module.exports = lineStyle;
/***/ },
/* 34 */
/***/ function(module, exports) {
module.exports = (ctx) => ctx.canvas[Symbol.for('mouseData')];
/***/ },
/* 35 */
/***/ function(module, exports, __webpack_require__) {
let moveTo = __webpack_require__(7), lineTo = __webpack_require__(6);
let moveToLineTo = (point, index) => index === 0 ?
moveTo(point[0], point[1]) :
lineTo(point[0], point[1]);
module.exports = moveToLineTo;
/***/ },
/* 36 */
/***/ function(module, exports, __webpack_require__) {
let beginPath = __webpack_require__(2)(),
closePath = __webpack_require__(3)();
let path = (...children) => [
beginPath,
children,
closePath
];
module.exports = path;
/***/ },
/* 37 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let cache = new Instruction('placeholder');
let placeHolder = () => cache;
module.exports = placeHolder;
/***/ },
/* 38 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let quadraticCurveTo = (cpx, cpy, x, y) => new Instruction('quadraticCurveTo', {
cpx,
cpy,
x,
y
});
module.exports = quadraticCurveTo;
/***/ },
/* 39 */
/***/ function(module, exports) {
let raf = (func) => {
requestAnimationFrame(() => raf(func));
return func();
};
module.exports = raf;
/***/ },
/* 40 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let rect = (...args) => new Instruction('rect',
args.length > 2 ?
{ x: args[0], y: args[1], width: args[2], height: args[3] } :
{ x: 0, y: 0, width: args[0], height: args[1] }
);
module.exports = rect;
/***/ },
/* 41 */
/***/ function(module, exports, __webpack_require__) {
//initialize all the properties
let identity = [1, 0, 0, 1, 0, 0],
matrix = new Float64Array(identity),
fillStyleStack = [],
strokeStyleStack = [],
lineStyleStack = [],
textStyleStack = [],
shadowStyleStack = [],
globalCompositeOperationStack = [],
globalAlphaStack = [],
imageSmoothingEnabledStack = [],
transformStack = new Float64Array(501 * 6),
transformStackIndex = 6,
concat = [].concat,
supportsEllipse = false;
if (typeof CanvasRenderingContext2D !== 'undefined') {
supportsEllipse = CanvasRenderingContext2D.prototype.hasOwnProperty('ellipse');
}
//transform points function
const transformPoints = __webpack_require__(1);
const cycleMouseData = __webpack_require__(4);
const increaseTransformStackSize = () => {
let cache = transformStack;
transformStack = new Float64Array(transformStack.length + 600); //add 100 more
transformStack.set(cache);
return this;
};
transformStack.set(identity);
const PI2 = Math.PI * 2;
let empty = (target) => target && target.splice(0, target.length);
module.exports = (...args) => {
let children = args.slice(0, -1),
ctx = args[args.length - 1];
let regions = ctx.canvas[Symbol.for('regions')],
mousePoints = ctx.canvas[Symbol.for('mousePoints')],
extensions = ctx.canvas[Symbol.for('extensions')];
let cache;
cycleMouseData(ctx);
empty(regions);
empty(mousePoints);
let len = children.length;
//flatten children during the loop process to save cpu
for (let i = 0; i < len; i++) {
let child = children[i];
//flattening algorithm
if (child && child.constructor === Array) {
children = concat.apply([], children);
child = children[i];
//repeat as necessary
while (child && child.constructor === Array) {
children = concat.apply([], children);
child = children[i];
}
len = children.length;
}
//child must be truthy
if (!child) {
continue;
}
let { props, type } = child;
if (type === 'transform') {
//copy transformStack values to matrix
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
//increase the index
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
//perform the transform math
transformStack[transformStackIndex - 6] = //d
matrix[0] * props[0] + matrix[2] * props[1];
transformStack[transformStackIndex - 5] = //b
matrix[1] * props[0] + matrix[3] * props[1];
transformStack[transformStackIndex - 4] = //c
matrix[0] * props[2] + matrix[2] * props[3];
transformStack[transformStackIndex - 3] = //d
matrix[1] * props[2] + matrix[3] * props[3];
transformStack[transformStackIndex - 2] = //e
matrix[0] * props[4] + matrix[2] * props[5] + matrix[4];
transformStack[transformStackIndex - 1] = //f
matrix[1] * props[4] + matrix[3] * props[5] + matrix[5];
//modify the ctx
ctx.setTransform(
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
);
continue;
}
if (type === 'setTransform') {
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
transformStack[transformStackIndex - 6] = props[0];//a
transformStack[transformStackIndex - 5] = props[1];//b
transformStack[transformStackIndex - 4] = props[2];//c
transformStack[transformStackIndex - 3] = props[3];//d
transformStack[transformStackIndex - 2] = props[4];//e
transformStack[transformStackIndex - 1] = props[5];//f
ctx.setTransform(props[0], props[1], props[2], props[3], props[4], props[5]);
continue;
}
if (type === 'scale') {
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
transformStack[transformStackIndex - 6] = matrix[0] * props.x; //a
transformStack[transformStackIndex - 5] = matrix[1] * props.x; //b
transformStack[transformStackIndex - 4] = matrix[2] * props.y; //c
transformStack[transformStackIndex - 3] = matrix[3] * props.y; //d
transformStack[transformStackIndex - 2] = matrix[4]; //e
transformStack[transformStackIndex - 1] = matrix[5]; //f
ctx.setTransform(
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
);
continue;
}
if (type === 'translate') {
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
transformStack[transformStackIndex - 6] = matrix[0]; //a
transformStack[transformStackIndex - 5] = matrix[1]; //b
transformStack[transformStackIndex - 4] = matrix[2]; //c
transformStack[transformStackIndex - 3] = matrix[3]; //d
transformStack[transformStackIndex - 2] = matrix[4] + matrix[0] * props.x + matrix[2] * props.y; //e
transformStack[transformStackIndex - 1] = matrix[5] + matrix[1] * props.x + matrix[3] * props.y; //f
ctx.setTransform(
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
);
continue;
}
if (type === 'rotate') {
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
transformStack[transformStackIndex - 6] =
matrix[0] * props.cos + matrix[2] * props.sin; //a
transformStack[transformStackIndex - 5] =
matrix[1] * props.cos + matrix[3] * props.sin; //b
transformStack[transformStackIndex - 4] =
matrix[0] * -props.sin + matrix[2] * props.cos; //c
transformStack[transformStackIndex - 3] =
matrix[1] * -props.sin + matrix[3] * props.cos; //d
transformStack[transformStackIndex - 2] = matrix[4]; //e
transformStack[transformStackIndex - 1] = matrix[5];//f
ctx.setTransform(
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
);
continue;
}
if (type === 'skewX') {
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
transformStack[transformStackIndex - 6] = matrix[0]; //a
transformStack[transformStackIndex - 5] = matrix[1]; //b
transformStack[transformStackIndex - 4] = //c
matrix[0] * props.x + matrix[2];
transformStack[transformStackIndex - 3] = //d
matrix[1] * props.x + matrix[3];
transformStack[transformStackIndex - 2] = matrix[4]; //e
transformStack[transformStackIndex - 1] = matrix[5]; //f
ctx.setTransform(
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
);
continue;
}
if (type === 'skewY') {
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
transformStackIndex += 6;
if (transformStackIndex > transformStack.length) {
increaseTransformStackSize();
}
transformStack[transformStackIndex - 6] =
matrix[0] * 1 + matrix[2] * props.y; //a
transformStack[transformStackIndex - 5] =
matrix[1] * 1 + matrix[3] * props.y; //b
transformStack[transformStackIndex - 4] = matrix[2]; //c
transformStack[transformStackIndex - 3] = matrix[3]; //d
transformStack[transformStackIndex - 2] = matrix[4]; //e
transformStack[transformStackIndex - 1] = matrix[5]; //f
ctx.setTransform(
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
);
continue;
}
if (type === 'restore') {
transformStackIndex -= 6;
matrix[0] = transformStack[transformStackIndex - 6];
matrix[1] = transformStack[transformStackIndex - 5];
matrix[2] = transformStack[transformStackIndex - 4];
matrix[3] = transformStack[transformStackIndex - 3];
matrix[4] = transformStack[transformStackIndex - 2];
matrix[5] = transformStack[transformStackIndex - 1];
ctx.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
continue;
}
if (type === 'fillRect') {
ctx.fillRect(props.x, props.y, props.width, props.height);
continue;
}
if (type === 'strokeRect') {
ctx.strokeRect(props.x, props.y, props.width, props.height);
continue;
}
if (type === 'clearRect') {
ctx.clearRect(props.x, props.y, props.width, props.height);
continue;
}
if (type === 'rect') {
ctx.rect(props.x, props.y, props.width, props.height);
continue;
}
if (type === 'fillStyle') {
fillStyleStack.push(ctx.fillStyle);
ctx.fillStyle = props.value;
continue;
}
if (type === 'strokeStyle') {
strokeStyleStack.push(ctx.strokeStyle);
ctx.strokeStyle = props.value;
continue;
}
if (type === 'endFillStyle') {
ctx.fillStyle = fillStyleStack.pop();
continue;
}
if (type === 'endStrokeStyle') {
ctx.strokeStyle = strokeStyleStack.pop();
continue;
}
if (type === 'lineStyle') {
lineStyleStack.push({
lineWidth: ctx.lineWidth,
lineCap: ctx.lineCap,
lineJoin: ctx.lineJoin,
miterLimit: ctx.miterLimit,
lineDash: ctx.getLineDash(),
lineDashOffset: ctx.lineDashOffset
});
if (props.lineWidth !== null) {
ctx.lineWidth = props.lineWidth;
}
if (props.lineCap !== null) {
ctx.lineCap = props.lineCap;
}
if (props.lineJoin !== null) {
ctx.lineJoin = props.lineJoin;
}
if (props.miterLimit !== null) {
ctx.miterLimit = props.miterLimit;
}
if (props.lineDash !== null) {
ctx.setLineDash(props.lineDash);
}
if (props.lineDashOffset !== null) {
ctx.lineDashOffset = props.lineDashOffset;
}
continue;
}
if (type === 'endLineStyle') {
cache = lineStyleStack.pop();
ctx.lineWidth = cache.lineWidth;
ctx.lineCap = cache.lineCap;
ctx.lineJoin = cache.lineJoin;
ctx.miterLimit = cache.miterLimit;
ctx.setLineDash(cache.lineDash);
ctx.lineDashOffset = cache.lineDashOffset;
continue;
}
if (type === 'textStyle') {
textStyleStack.push({
font: ctx.font,
textAlign: ctx.textAlign,
textBaseline: ctx.textBaseline,
direction: ctx.direction
});
if (props.font !== null) {
ctx.font = props.font;
}
if (props.textAlign !== null) {
ctx.textAlign = props.textAlign;
}
if (props.textBaseline !== null) {
ctx.textBaseline = props.textBaseline;
}
if (props.direction !== null) {
ctx.direction = props.direction;
}
continue;
}
if (type === 'endTextStyle') {
cache = textStyleStack.pop();
ctx.font = cache.font;
ctx.textAlign = cache.textAlign;
ctx.textBaseline = cache.textBaseline;
ctx.direction = cache.direction;
continue;
}
if (type === 'shadowStyle') {
shadowStyleStack.push({
shadowBlur: ctx.shadowBlur,
shadowColor: ctx.shadowColor,
shadowOffsetX: ctx.shadowOffsetX,
shadowOffsetY: ctx.shadowOffsetY
});
if (props.shadowBlur !== null) {
ctx.shadowBlur = props.shadowBlur;
}
if (props.shadowColor !== null) {
ctx.shadowColor = props.shadowColor;
}
if (props.shadowOffsetX !== null) {
ctx.shadowOffsetX = props.shadowOffsetX;
}
if (props.shadowOffsetY !== null) {
ctx.shadowOffsetY = props.shadowOffsetY;
}
continue;
}
if (type === 'endShadowStyle') {
cache = shadowStyleStack.pop();
ctx.shadowBlur = cache.shadowBlur;
ctx.shadowColor = cache.shadowColor;
ctx.shadowOffsetX = cache.shadowOffsetX;
ctx.shadowOffsetY = cache.shadowOffsetY;
continue;
}
if (type === 'strokeText') {
if (props.maxWidth) {
ctx.strokeText(props.text, props.x, props.y, props.maxWidth);
continue;
}
ctx.strokeText(props.text, props.x, props.y);
continue;
}
if (type === 'fillText') {
if (props.maxWidth) {
ctx.fillText(props.text, props.x, props.y, props.maxWidth);
continue;
}
ctx.fillText(props.text, props.x, props.y);
continue;
}
if (type === 'drawImage') {
ctx.drawImage(props.img, props.dx, props.dy);
continue;
}
if (type === 'drawImageSize') {
ctx.drawImage(props.img, props.dx, props.dy, props.dWidth, props.dHeight);
continue;
}
if (type === 'drawImageSource') {
ctx.drawImage(props.img, props.sx, props.sy, props.sWidth, props.sHeight, props.dx, props.dy, props.dWidth, props.dHeight);
continue;
}
if (type === 'strokeArc') {
ctx.beginPath();
ctx.arc(props.x, props.y, props.r, props.startAngle, props.endAngle, props.counterclockwise);
ctx.closePath();
ctx.stroke();
continue;
}
if (type === 'fillArc') {
ctx.beginPath();
ctx.arc(props.x, props.y, props.r, props.startAngle, props.endAngle, props.counterclockwise);
ctx.closePath();
ctx.fill();
continue;
}
if (type === 'moveTo') {
ctx.moveTo(props.x, props.y);
continue;
}
if (type === 'lineTo') {
ctx.lineTo(props.x, props.y);
continue;
}
if (type === 'bezierCurveTo') {
ctx.bezierCurveTo(props.cp1x, props.cp1y, props.cp2x, props.cp2y, props.x, props.y);
continue;
}
if (type === 'quadraticCurveTo') {
ctx.quadraticCurveTo(props.cpx, props.cpy, props.x, props.y);
continue;
}
if (type === 'arc') {
ctx.arc(props.x, props.y, props.r, props.startAngle, props.endAngle, props.counterclockwise);
continue;
}
if (type === 'arcTo') {
ctx.arcTo(props.x1, props.y1, props.x2, props.y2, props.r);
continue;
}
if (type === 'ellipse') {
//if the method is provided by the browser
if (supportsEllipse) {
ctx.ellipse(
props.x,
props.y,
props.radiusX,
props.radiusY,
props.rotation,
props.startAngle,
props.endAngle,
props.anticlockwise
);
continue;
}
ctx.save();
ctx.translate(props.x, props.y);
ctx.rotate(props.rotation);
ctx.scale(props.radiusX, props.radiusY);
ctx.arc(0, 0, 1, props.startAngle, props.endAngle, props.anticlockwise);
ctx.restore();
continue;
}
if (type === 'globalCompositeOperation') {
globalCompositeOperationStack.push(ctx.globalCompositeOperation);
ctx.globalCompositeOperation = props.value;
continue;
}
if (type === 'endGlobalCompositeOperation') {
ctx.globalCompositeOperation = globalCompositeOperationStack.pop();
continue;
}
if (type === 'fill') {
ctx.fill();
continue;
}
if (type === 'stroke') {
ctx.stroke();
continue;
}
if (type === 'beginClip') {
ctx.save();
ctx.beginPath();
continue;
}
if (type === 'clip') {
ctx.clip();
continue;
}
if (type === 'endClip') {
ctx.restore();
continue;
}
if (type === 'beginPath') {
ctx.beginPath();
continue;
}
if (type === 'closePath') {
ctx.closePath();
continue;
}
if (type === 'globalAlpha') {
globalAlphaStack.push(ctx.globalAlpha);
ctx.globalAlpha *= props.value;
continue;
}
if (type === 'endGlobalAlpha') {
ctx.globalAlpha = globalAlphaStack.pop();
continue;
}
if (type === 'hitRect' && regions) {
cache = [
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
];
regions.push({
id: props.id,
points: props.points,
matrix: cache,
//rectangle!
polygon: false,
hover: false,
touched: false,
clicked: false
});
}
if (type === 'hitRegion' && regions) {
cache = [
transformStack[transformStackIndex - 6],
transformStack[transformStackIndex - 5],
transformStack[transformStackIndex - 4],
transformStack[transformStackIndex - 3],
transformStack[transformStackIndex - 2],
transformStack[transformStackIndex - 1]
];
regions.push({
id: props.id,
points: props.points,
matrix: cache,
polygon: true,
hover: false,
touched: false,
clicked: false
});
continue;
}
if (type === 'imageSmoothingEnabled') {
imageSmoothingEnabledStack.push(ctx.imageSmoothingEnabled);
ctx.imageSmoothingEnabled = props.value;
continue;
}
if (type === 'endImageSmoothingEnabled') {
ctx.imageSmoothingEnabled = imageSmoothingEnabledStack.pop();
continue;
}
if (extensions && extensions[type]) {
extensions[type](props, ctx);
continue;
}
}
};
/***/ },
/* 42 */
/***/ function(module, exports, __webpack_require__) {
let setTransform = __webpack_require__(9);
let resetTransform = (...children) => setTransform([1, 0, 0, 1, 0, 0], children);
module.exports = resetTransform;
/***/ },
/* 43 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let rotate = (r, ...children) => [
new Instruction('rotate', { cos: Math.cos(r), sin: Math.sin(r) }),
children,
end
];
module.exports = rotate;
/***/ },
/* 44 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let scale = (x, y, ...children) => {
if (typeof y !== 'number') {
children = [y].concat(children);
y = x;
}
return [
new Instruction('scale', { x, y }),
children,
end
];
};
module.exports = scale;
/***/ },
/* 45 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endShadowStyle');
let shadowStyle = (value, ...children) => {
value = value || {};
var result = {
shadowBlur: null,
shadowColor: null,
shadowOffsetX: null,
shadowOffsetY: null
};
if (typeof value.shadowBlur !== 'undefined') {
result.shadowBlur = value.shadowBlur;
}
if (typeof value.shadowColor !== 'undefined') {
result.shadowColor = value.shadowColor;
}
if (typeof value.shadowOffsetX !== 'undefined') {
result.shadowOffsetX = value.shadowOffsetX;
}
if (typeof value.direction !== 'undefined') {
result.shadowOffsetY = value.shadowOffsetY;
}
return [
new Instruction('shadowStyle', value),
children,
end
];
};
module.exports = shadowStyle;
/***/ },
/* 46 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let skewX = (x, ...children) => [
new Instruction('skewX', { x: Math.tan(x) }),
children,
end
];
module.exports = skewX;
/***/ },
/* 47 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let skewY = (x, ...children) => [
new Instruction('skewY', { y: Math.tan(y) }),
children,
end
];
module.exports = skewY;
/***/ },
/* 48 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let cache = new Instruction('stroke');
let stroke = () => cache;
module.exports = stroke;
/***/ },
/* 49 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0),
pi2 = Math.PI * 2;
let strokeArc = (...args) => {
let [x, y, r, startAngle, endAngle, counterclockwise] = args;
let props = { x: 0, y: 0, r: x, startAngle: 0, endAngle: pi2, counterclockwise: false };
if (args.length > 3) {
props.startAngle = startAngle;
props.endAngle = endAngle;
props.counterclockwise = !!counterclockwise;
}
if (args.length > 1){
props.x = x;
props.y = y;
props.r = r;
}
return new Instruction("strokeArc", props);
};
module.exports = strokeArc;
/***/ },
/* 50 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let strokeRect = (...args) => new Instruction('strokeRect',
args.length > 2 ?
{ x: args[0], y: args[1], width: args[2], height: args[3] } :
{ x: 0, y: 0, width: args[0], height: args[1] }
);
module.exports = strokeRect;
/***/ },
/* 51 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endStrokeStyle');
let strokeStyle = (value, ...children) => [
new Instruction('strokeStyle', { value }),
children,
end
];
module.exports = strokeStyle;
/***/ },
/* 52 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let strokeText = (...args) => {
let [text, x, y, maxWidth] = args;
if (args.length < 4) {
maxWidth = null;
}
if (args.length < 3) {
x = 0;
y = 0;
}
return new Instruction('strokeText', {
text,
x,
y,
maxWidth
});
};
module.exports = strokeText;
/***/ },
/* 53 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('endTextStyle');
let textStyle = (value, ...children) => {
value = value || {};
var result = {
font: null,
textAlign: null,
textBaseline: null,
direction: null
};
if (typeof value.font !== 'undefined') {
result.font = value.font;
}
if (typeof value.textAlign !== 'undefined') {
result.textAlign = value.textAlign;
}
if (typeof value.textBaseline !== 'undefined') {
result.textBaseline = value.textBaseline;
}
if (typeof value.direction !== 'undefined') {
result.direction = value.direction;
}
return [
new Instruction('textStyle', result),
children,
end
];
};
module.exports = textStyle;
/***/ },
/* 54 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let transform = (values, ...children) => {
return [
new Instruction('transform',[
values[0],
values[1],
values[2],
values[3],
values[4],
values[5]
]),
children,
end
];
};
module.exports = transform;
/***/ },
/* 55 */
/***/ function(module, exports, __webpack_require__) {
let Instruction = __webpack_require__(0);
let end = new Instruction('restore');
let translate = (x, y, ...children) => [
new Instruction('translate', { x: x, y: y }),
children,
end
];
module.exports = translate;
/***/ },
/* 56 */
/***/ function(module, exports) {
// Source: http://jsfiddle.net/vWx8V/
// http://stackoverflow.com/questions/5603195/full-list-of-javascript-keycodes
/**
* Conenience method returns corresponding value for given keyName or keyCode.
*
* @param {Mixed} keyCode {Number} or keyName {String}
* @return {Mixed}
* @api public
*/
exports = module.exports = function(searchInput) {
// Keyboard Events
if (searchInput && 'object' === typeof searchInput) {
var hasKeyCode = searchInput.which || searchInput.keyCode || searchInput.charCode
if (hasKeyCode) searchInput = hasKeyCode
}
// Numbers
if ('number' === typeof searchInput) return names[searchInput]
// Everything else (cast to string)
var search = String(searchInput)
// check codes
var foundNamedKey = codes[search.toLowerCase()]
if (foundNamedKey) return foundNamedKey
// check aliases
var foundNamedKey = aliases[search.toLowerCase()]
if (foundNamedKey) return foundNamedKey
// weird character?
if (search.length === 1) return search.charCodeAt(0)
return undefined
}
/**
* Get by name
*
* exports.code['enter'] // => 13
*/
var codes = exports.code = exports.codes = {
'backspace': 8,
'tab': 9,
'enter': 13,
'shift': 16,
'ctrl': 17,
'alt': 18,
'pause/break': 19,
'caps lock': 20,
'esc': 27,
'space': 32,
'page up': 33,
'page down': 34,
'end': 35,
'home': 36,
'left': 37,
'up': 38,
'right': 39,
'down': 40,
'insert': 45,
'delete': 46,
'command': 91,
'left command': 91,
'right command': 93,
'numpad *': 106,
'numpad +': 107,
'numpad -': 109,
'numpad .': 110,
'numpad /': 111,
'num lock': 144,
'scroll lock': 145,
'my computer': 182,
'my calculator': 183,
';': 186,
'=': 187,
',': 188,
'-': 189,
'.': 190,
'/': 191,
'`': 192,
'[': 219,
'\\': 220,
']': 221,
"'": 222
}
// Helper aliases
var aliases = exports.aliases = {
'windows': 91,
'⇧': 16,
'⌥': 18,
'⌃': 17,
'⌘': 91,
'ctl': 17,
'control': 17,
'option': 18,
'pause': 19,
'break': 19,
'caps': 20,
'return': 13,
'escape': 27,
'spc': 32,
'pgup': 33,
'pgdn': 34,
'ins': 45,
'del': 46,
'cmd': 91
}
/*!
* Programatically add the following
*/
// lower case chars
for (i = 97; i < 123; i++) codes[String.fromCharCode(i)] = i - 32
// numbers
for (var i = 48; i < 58; i++) codes[i - 48] = i
// function keys
for (i = 1; i < 13; i++) codes['f'+i] = i + 111
// numpad keys
for (i = 0; i < 10; i++) codes['numpad '+i] = i + 96
/**
* Get by code
*
* exports.name[13] // => 'Enter'
*/
var names = exports.names = exports.title = {} // title for backward compat
// Create reverse mapping
for (i in codes) names[codes[i]] = i
// Add aliases
for (var alias in aliases) {
codes[alias] = aliases[alias]
}
/***/ },
/* 57 */
/***/ function(module, exports) {
module.exports = function (point, vs) {
// ray-casting algorithm based on
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
var x = point[0], y = point[1];
var inside = false;
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
var xi = vs[i][0], yi = vs[i][1];
var xj = vs[j][0], yj = vs[j][1];
var intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
};
/***/ },
/* 58 */
/***/ function(module, exports, __webpack_require__) {
module.exports = {
'activeRegions': __webpack_require__(10),
'arc': __webpack_require__(11),
'arcTo': __webpack_require__(12),
'beginPath': __webpack_require__(2),
'bezierCurveTo': __webpack_require__(13),
'clearRect': __webpack_require__(14),
'clip': __webpack_require__(15),
'clipPath': __webpack_require__(16),
'closePath': __webpack_require__(3),
'createRegularPolygon': __webpack_require__(17),
'createWrapper': __webpack_require__(18),
'cycleMouseData': __webpack_require__(4),
'drawImage': __webpack_require__(19),
'ellipse': __webpack_require__(20),
'fill': __webpack_require__(21),
'fillArc': __webpack_require__(22),
'fillRect': __webpack_require__(23),
'fillStyle': __webpack_require__(24),
'fillText': __webpack_require__(25),
'globalAlpha': __webpack_require__(26),
'globalCompositeOperation': __webpack_require__(27),
'hitRect': __webpack_require__(28),
'hitRegion': __webpack_require__(29),
'imageSmoothingEnabled': __webpack_require__(30),
'initialize': __webpack_require__(31),
'Instruction': __webpack_require__(0),
'invertMatrix': __webpack_require__(5),
'keyData': __webpack_require__(32),
'lineStyle': __webpack_require__(33),
'lineTo': __webpack_require__(6),
'mouseData': __webpack_require__(34),
'moveTo': __webpack_require__(7),
'moveToLineTo': __webpack_require__(35),
'path': __webpack_require__(36),
'placeHolder': __webpack_require__(37),
'pointInRect': __webpack_require__(8),
'quadraticCurveTo': __webpack_require__(38),
'raf': __webpack_require__(39),
'rect': __webpack_require__(40),
'render': __webpack_require__(41),
'resetTransform': __webpack_require__(42),
'rotate': __webpack_require__(43),
'scale': __webpack_require__(44),
'setTransform': __webpack_require__(9),
'shadowStyle': __webpack_require__(45),
'skewX': __webpack_require__(46),
'skewY': __webpack_require__(47),
'stroke': __webpack_require__(48),
'strokeArc': __webpack_require__(49),
'strokeRect': __webpack_require__(50),
'strokeStyle': __webpack_require__(51),
'strokeText': __webpack_require__(52),
'textStyle': __webpack_require__(53),
'transform': __webpack_require__(54),
'transformPoints': __webpack_require__(1),
'translate': __webpack_require__(55)
};
/***/ }
/******/ ]);
});
},{}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImUyZCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIihmdW5jdGlvbiB3ZWJwYWNrVW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbihyb290LCBmYWN0b3J5KSB7XG5cdGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0Jylcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKTtcblx0ZWxzZSBpZih0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpXG5cdFx0ZGVmaW5lKFtdLCBmYWN0b3J5KTtcblx0ZWxzZSBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpXG5cdFx0ZXhwb3J0c1tcImUyZFwiXSA9IGZhY3RvcnkoKTtcblx0ZWxzZVxuXHRcdHJvb3RbXCJlMmRcIl0gPSBmYWN0b3J5KCk7XG59KSh0aGlzLCBmdW5jdGlvbigpIHtcbnJldHVybiAvKioqKioqLyAoZnVuY3Rpb24obW9kdWxlcykgeyAvLyB3ZWJwYWNrQm9vdHN0cmFwXG4vKioqKioqLyBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbi8qKioqKiovIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuLyoqKioqKi8gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuLyoqKioqKi8gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbi8qKioqKiovIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbi8qKioqKiovIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSlcbi8qKioqKiovIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuXG4vKioqKioqLyBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbi8qKioqKiovIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4vKioqKioqLyBcdFx0XHRpOiBtb2R1bGVJZCxcbi8qKioqKiovIFx0XHRcdGw6IGZhbHNlLFxuLyoqKioqKi8gXHRcdFx0ZXhwb3J0czoge31cbi8qKioqKiovIFx0XHR9O1xuXG4vKioqKioqLyBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4vKioqKioqLyBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbi8qKioqKiovIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4vKioqKioqLyBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4vKioqKioqLyBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbi8qKioqKiovIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4vKioqKioqLyBcdH1cblxuXG4vKioqKioqLyBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbi8qKioqKiovIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbi8qKioqKiovIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuLyoqKioqKi8gXHQvLyBpZGVudGl0eSBmdW5jdGlvbiBmb3IgY2FsbGluZyBoYXJtb255IGltcG9ydHMgd2l0aCB0aGUgY29ycmVjdCBjb250ZXh0XG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18uaSA9IGZ1bmN0aW9uKHZhbHVlKSB7IHJldHVybiB2YWx1ZTsgfTtcblxuLyoqKioqKi8gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbi8qKioqKiovIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4vKioqKioqLyBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuLyoqKioqKi8gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbi8qKioqKiovIFx0XHRcdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcbi8qKioqKiovIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbi8qKioqKiovIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbi8qKioqKiovIFx0XHRcdH0pO1xuLyoqKioqKi8gXHRcdH1cbi8qKioqKiovIFx0fTtcblxuLyoqKioqKi8gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbi8qKioqKiovIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbi8qKioqKiovIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4vKioqKioqLyBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuLyoqKioqKi8gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbi8qKioqKiovIFx0XHRyZXR1cm4gZ2V0dGVyO1xuLyoqKioqKi8gXHR9O1xuXG4vKioqKioqLyBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbi8qKioqKiovIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbi8qKioqKiovIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuLyoqKioqKi8gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbi8qKioqKiovIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gNTgpO1xuLyoqKioqKi8gfSlcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4vKioqKioqLyAoW1xuLyogMCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbmNsYXNzIEluc3RydWN0aW9uIHtcclxuICBjb25zdHJ1Y3Rvcih0eXBlLCBwcm9wcykge1xyXG4gICAgdGhpcy50eXBlID0gdHlwZTtcclxuICAgIHRoaXMucHJvcHMgPSBwcm9wcztcclxuICAgIHJldHVybiBPYmplY3Quc2VhbCh0aGlzKTtcclxuICB9XHJcbn1cclxuXHJcbk9iamVjdC5zZWFsKEluc3RydWN0aW9uKTtcclxuT2JqZWN0LnNlYWwoSW5zdHJ1Y3Rpb24ucHJvdG90eXBlKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gSW5zdHJ1Y3Rpb247XHJcblxuXG4vKioqLyB9LFxuLyogMSAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbmxldCB0cmFuc2Zvcm1Qb2ludHMgPSAocG9pbnRzLCBtYXRyaXgpID0+IHtcclxuICBsZXQgcmVzdWx0ID0gW10sXHJcbiAgICAgIHgsIHk7XHJcblxyXG4gIGZvcihsZXQgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcclxuICAgIFt4LCB5XSA9IHBvaW50c1tpXTtcclxuICAgIHJlc3VsdC5wdXNoKFtcclxuICAgICAgbWF0cml4WzBdICogeCArIG1hdHJpeFsyXSAqIHkgKyBtYXRyaXhbNF0sXHJcbiAgICAgIG1hdHJpeFsxXSAqIHggKyBtYXRyaXhbM10gKiB5ICsgbWF0cml4WzVdXHJcbiAgICBdKTtcclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gdHJhbnNmb3JtUG9pbnRzO1xyXG5cblxuLyoqKi8gfSxcbi8qIDIgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApLFxyXG4gIGNhY2hlID0gbmV3IEluc3RydWN0aW9uKCdiZWdpblBhdGgnKTtcclxuXHJcbmxldCBiZWdpblBhdGggPSAoKSA9PiBjYWNoZTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gYmVnaW5QYXRoO1xuXG4vKioqLyB9LFxuLyogMyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBjYWNoZSA9IG5ldyBJbnN0cnVjdGlvbignY2xvc2VQYXRoJyk7XHJcblxyXG5sZXQgY2xvc2VQYXRoID0gKCkgPT4gY2FjaGU7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNsb3NlUGF0aDtcclxuXG5cbi8qKiovIH0sXG4vKiA0ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcblxuXHJcbmxldCBjeWNsZU1vdXNlRGF0YSA9IChjdHgpID0+IHtcclxuICBsZXQgbW91c2VEYXRhID0gY3R4LmNhbnZhc1tTeW1ib2wuZm9yKCdtb3VzZURhdGEnKV07XHJcbiAgaWYgKG1vdXNlRGF0YSkge1xyXG4gICAgbW91c2VEYXRhLmR4ID0gbW91c2VEYXRhLnggLSBtb3VzZURhdGEucHJldmlvdXNYO1xyXG4gICAgbW91c2VEYXRhLmR5ID0gbW91c2VEYXRhLnkgLSBtb3VzZURhdGEucHJldmlvdXNZO1xyXG5cclxuICAgIG1vdXNlRGF0YS5wcmV2aW91c1ggPSBtb3VzZURhdGEueDtcclxuICAgIG1vdXNlRGF0YS5wcmV2aW91c1kgPSBtb3VzZURhdGEueTtcclxuXHJcbiAgICBtb3VzZURhdGEuY2xpY2tlZCA9IDA7XHJcbiAgfVxyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjeWNsZU1vdXNlRGF0YTtcblxuLyoqKi8gfSxcbi8qIDUgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuXG5sZXQgZGV0ID0gMDtcclxubGV0IGludmVydE1hdHJpeCA9IChbYSwgYiwgYywgZCwgZSwgZl0pID0+IChcclxuICBkZXQgPSAxIC8gKGEgKiBkIC0gYyAqIGIpLFxyXG4gIFtcclxuICAgIGQgKiBkZXQsXHJcbiAgICAtYyAqIGRldCxcclxuICAgIC1iICogZGV0LFxyXG4gICAgYSAqIGRldCxcclxuICAgIChiICogZiAtIGUgKiBkKSAqIGRldCxcclxuICAgIChlICogYiAtIGEgKiBmKSAqIGRldFxyXG4gIF1cclxuKTtcclxuIG1vZHVsZS5leHBvcnRzID0gaW52ZXJ0TWF0cml4O1xuXG4vKioqLyB9LFxuLyogNiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgbGluZVRvID0gKHgsIHkpID0+IG5ldyBJbnN0cnVjdGlvbignbGluZVRvJywgeyB4LCB5IH0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBsaW5lVG87XHJcblxuXG4vKioqLyB9LFxuLyogNyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgbW92ZVRvID0gKHgsIHkpID0+IG5ldyBJbnN0cnVjdGlvbignbW92ZVRvJywgeyB4LCB5IH0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBtb3ZlVG87XHJcblxuXG4vKioqLyB9LFxuLyogOCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbmxldCBwb2ludEluUmVjdCA9IChbcHgsIHB5XSwgW1t4LCB5XSwgW3dpZHRoLCBoZWlnaHRdXSkgPT4gcHggPiB4ICYmIHB5ID4geSAmJiBweCA8IHdpZHRoICYmIHB5IDwgaGVpZ2h0O1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBwb2ludEluUmVjdDtcblxuLyoqKi8gfSxcbi8qIDkgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xyXG5sZXQgZW5kID0gbmV3IEluc3RydWN0aW9uKCdyZXN0b3JlJyk7XHJcblxyXG5sZXQgc2V0VHJhbnNmb3JtID0gKG1hdHJpeCwgLi4uY2hpbGRyZW4pID0+IFtcclxuICBuZXcgSW5zdHJ1Y3Rpb24oJ3NldFRyYW5zZm9ybScsIFtcclxuICAgIG1hdHJpeFswXSxcclxuICAgIG1hdHJpeFsxXSxcclxuICAgIG1hdHJpeFsyXSxcclxuICAgIG1hdHJpeFszXSxcclxuICAgIG1hdHJpeFs0XSxcclxuICAgIG1hdHJpeFs1XVxyXG4gIF0pLFxyXG4gIGNoaWxkcmVuLFxyXG4gIGVuZFxyXG5dO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBzZXRUcmFuc2Zvcm07XG5cbi8qKiovIH0sXG4vKiAxMCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBwb2ludEluUG9seWdvbiA9IF9fd2VicGFja19yZXF1aXJlX18oNTcpO1xyXG5sZXQgdHJhbnNmb3JtUG9pbnRzID0gX193ZWJwYWNrX3JlcXVpcmVfXygxKTtcclxubGV0IGludmVydE1hdHJpeCA9IF9fd2VicGFja19yZXF1aXJlX18oNSk7XHJcbmxldCBwb2ludEluUmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oOCk7XHJcblxyXG5sZXQgbWF0cml4ID0gbmV3IEZsb2F0NjRBcnJheSg2KTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gKGN0eCkgPT4ge1xyXG4gIGxldCByZWdpb25zID0gY3R4LmNhbnZhc1tTeW1ib2wuZm9yKCdyZWdpb25zJyldLFxyXG4gICAgbW91c2VQb2ludHMgPSBjdHguY2FudmFzW1N5bWJvbC5mb3IoJ21vdXNlUG9pbnRzJyldLFxyXG4gICAgbW91c2VEYXRhID0gY3R4LmNhbnZhc1tTeW1ib2wuZm9yKCdtb3VzZURhdGEnKV0sXHJcbiAgICByZXN1bHRzID0ge307XHJcblxyXG4gIC8vdGhlIG1vdXNlIG1pZ2h0IGhhdmUgaGVsZCBzdGlsbCwgYWRkIHRoZSBjdXJyZW50IG1vdXNlIHBvc2l0aW9uXHJcbiAgaWYgKG1vdXNlUG9pbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgbW91c2VQb2ludHMucHVzaChbbW91c2VEYXRhLngsIG1vdXNlRGF0YS55LCBtb3VzZURhdGEuc3RhdGVdKTtcclxuICB9XHJcblxyXG4gIGZvcihsZXQgcmVnaW9uIG9mIHJlZ2lvbnMpIHtcclxuXHJcbiAgICAvL2ludmVydCB0aGUgcmVnaW9uIG1hdHJpeCBhbmQgdHJhbnNmb3JtIHRoZSBtb3VzZSBwb2ludHNcclxuICAgIGxldCB0cmFuc2Zvcm1lZE1vdXNlUG9pbnRzID0gdHJhbnNmb3JtUG9pbnRzKG1vdXNlUG9pbnRzLCBpbnZlcnRNYXRyaXgocmVnaW9uLm1hdHJpeCkpO1xyXG4gICAgLy90aGUgbW91c2UgcG9pbnRzIGFyZSBub3cgcmVsYXRpdmUgdG8gdGhlIG1vdXNlIHJlZ2lvblxyXG5cclxuICAgIGlmICghcmVnaW9uLnBvbHlnb24pIHtcclxuICAgICAgZm9yIChsZXQgbW91c2VQb2ludCBvZiB0cmFuc2Zvcm1lZE1vdXNlUG9pbnRzKSB7XHJcbiAgICAgICAgaWYgKHBvaW50SW5SZWN0KG1vdXNlUG9pbnQsIHJlZ2lvbi5wb2ludHMpKSB7XHJcbiAgICAgICAgICByZWdpb24uaG92ZXIgPSB0cnVlO1xyXG4gICAgICAgICAgcmVnaW9uLmNsaWNrZWQgPSAhIW1vdXNlRGF0YS5jbGlja2VkO1xyXG4gICAgICAgICAgcmVzdWx0c1tyZWdpb24uaWRdID0gcmVnaW9uO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8vbG9vcCBvdmVyIGVhY2ggcG9pbnQgdW50aWwgb25lIGlzIG1hdGNoZWRcclxuICAgIGZvcihsZXQgbW91c2VQb2ludCBvZiB0cmFuc2Zvcm1lZE1vdXNlUG9pbnRzKSB7XHJcbiAgICAgIGlmIChwb2ludEluUG9seWdvbihtb3VzZVBvaW50LCByZWdpb24ucG9pbnRzKSkge1xyXG4gICAgICAgIHJlZ2lvbi5ob3ZlciA9IHRydWU7XHJcbiAgICAgICAgcmVnaW9uLmNsaWNrZWQgPSAhIW1vdXNlRGF0YS5jbGlja2VkO1xyXG4gICAgICAgIHJlc3VsdHNbcmVnaW9uLmlkXSA9IHJlZ2lvbjtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gcmVzdWx0cztcclxufTtcblxuLyoqKi8gfSxcbi8qIDExICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKSxcclxuICAgIHBpMiA9IE1hdGguUEkgKiAyO1xyXG5cclxubGV0IGFyYyA9ICguLi5hcmdzKSA9PiB7XHJcbiAgbGV0ICBbeCwgeSwgciwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIGNvdW50ZXJjbG9ja3dpc2VdID0gYXJncztcclxuICBsZXQgcHJvcHMgPSB7IHg6IDAsIHk6IDAsIHI6IHgsIHN0YXJ0QW5nbGU6IDAsIGVuZEFuZ2xlOiBwaTIsIGNvdW50ZXJjbG9ja3dpc2U6IGZhbHNlIH07XHJcblxyXG5cclxuICBpZiAoYXJncy5sZW5ndGggPiAzKSB7XHJcbiAgICBwcm9wcy5zdGFydEFuZ2xlID0gc3RhcnRBbmdsZTtcclxuICAgIHByb3BzLmVuZEFuZ2xlID0gZW5kQW5nbGU7XHJcbiAgICBwcm9wcy5jb3VudGVyY2xvY2t3aXNlID0gISFjb3VudGVyY2xvY2t3aXNlO1xyXG4gIH1cclxuXHJcbiAgaWYgKGFyZ3MubGVuZ3RoID4gMSl7XHJcbiAgICBwcm9wcy54ID0geDtcclxuICAgIHByb3BzLnkgPSB5O1xyXG4gICAgcHJvcHMuciA9IHI7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gbmV3IEluc3RydWN0aW9uKFwiYXJjXCIsICBwcm9wcyk7XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGFyYztcclxuXG5cbi8qKiovIH0sXG4vKiAxMiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgYXJjVG8gPSAoeDEsIHkxLCB4MiwgeTIsIHIpID0+IG5ldyBJbnN0cnVjdGlvbignYXJjVG8nLCB7IHgxLCB5MSwgeDIsIHkyLCByIH0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBhcmNUbztcclxuXG5cbi8qKiovIH0sXG4vKiAxMyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgYmV6aWVyQ3VydmVUbyA9IChjcDF4LCBjcDF5LCBjcDJ4LCBjcDJ5LCB4LCB5KSA9PiBuZXcgSW5zdHJ1Y3Rpb24oJ2JlemllckN1cnZlVG8nLCB7XHJcbiAgY3AxeCxcclxuICBjcDF5LFxyXG4gIGNwMngsXHJcbiAgY3AyeSxcclxuICB4LFxyXG4gIHlcclxufSk7XHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBiZXppZXJDdXJ2ZVRvO1xyXG5cblxuLyoqKi8gfSxcbi8qIDE0ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBjbGVhclJlY3QgPSAoLi4uYXJncykgPT4gbmV3IEluc3RydWN0aW9uKCdjbGVhclJlY3QnLFxyXG4gIGFyZ3MubGVuZ3RoID4gMiA/XHJcbiAgICB7IHg6IGFyZ3NbMF0sIHk6IGFyZ3NbMV0sIHdpZHRoOiBhcmdzWzJdLCBoZWlnaHQ6IGFyZ3NbM10gfSA6XHJcbiAgICB7IHg6IDAsIHk6IDAsIHdpZHRoOiBhcmdzWzBdLCBoZWlnaHQ6IGFyZ3NbMV0gfVxyXG4pO1xyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY2xlYXJSZWN0O1xyXG5cblxuLyoqKi8gfSxcbi8qIDE1ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBiZWdpbiA9IG5ldyBJbnN0cnVjdGlvbignYmVnaW5DbGlwJyksXHJcbiAgcGVyZm9ybUNsaXAgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2NsaXAnKSxcclxuICBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2VuZENsaXAnKTtcclxuXHJcbmxldCBjbGlwID0gKHBhdGgsIC4uLmNoaWxkcmVuKSA9PiBbXHJcbiAgYmVnaW4sXHJcbiAgcGF0aCxcclxuICBwZXJmb3JtQ2xpcCxcclxuICBjaGlsZHJlbixcclxuICBlbmRcclxuXTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY2xpcDtcclxuXG5cbi8qKiovIH0sXG4vKiAxNiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBjYWNoZSA9IG5ldyBJbnN0cnVjdGlvbignY2xpcFBhdGgnKTtcclxuXHJcbmxldCBjbGlwUGF0aCA9ICgpID0+IGNhY2hlO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjbGlwUGF0aDtcclxuXG5cbi8qKiovIH0sXG4vKiAxNyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbmxldCBjcmVhdGVSZWd1bGFyUG9seWdvbiA9IChyYWRpdXMgPSAwLCBwb3NpdGlvbiA9IFswLCAwXSwgc2lkZXMgPSAzKSA9PiB7XHJcbiAgbGV0IHBvbHlnb24gPSBbXTtcclxuICBmb3IobGV0IGkgPSAwOyBpIDwgc2lkZXM7IGkrKykge1xyXG4gICAgcG9seWdvbi5wdXNoKFtcclxuICAgICAgcG9zaXRpb25bMF0gKyByYWRpdXMgKiBNYXRoLmNvcyhNYXRoLlBJICogMiAqIGkgLyBzaWRlcyksXHJcbiAgICAgIHBvc2l0aW9uWzFdICsgcmFkaXVzICogTWF0aC5zaW4oTWF0aC5QSSAqIDIgKiBpIC8gc2lkZXMpXHJcbiAgICBdKTtcclxuICB9XHJcbiAgcmV0dXJuIHBvbHlnb247XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVJlZ3VsYXJQb2x5Z29uO1xyXG5cblxuLyoqKi8gfSxcbi8qIDE4ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcblxubGV0IGNvbmNhdCA9IFtdLmNvbmNhdDtcclxuXHJcbmxldCBjcmVhdGVXcmFwcGVyID0gKC4uLmFyZ3MpID0+IHtcclxuICBmb3IobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xyXG4gICAgLy9wYXJzZSBhbmQgZmxhdHRlbiB0aGUgYXJndW1lbnRzXHJcbiAgICB3aGlsZSAoYXJnc1tpXSAmJiBhcmdzW2ldLmNvbnN0cnVjdG9yID09PSBBcnJheSkge1xyXG4gICAgICBhcmdzID0gY29uY2F0LmFwcGx5KFtdLCBhcmdzKS5maWx0ZXIoQm9vbGVhbik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFhcmdzW2ldKSB7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCB7IHR5cGUgfSA9IGFyZ3NbaV07XHJcbiAgICBpZiAodHlwZSA9PT0gJ3BsYWNlaG9sZGVyJykge1xyXG4gICAgICAvLyBpIGlzIHNldCB0byB0aGUgcGxhY2Vob2xkZXIgaW5kZXggbm93XHJcblxyXG4gICAgICAvL25vdyBncmFiIGFsbCB0aGUgZWxlbWVudHMgdG8gdGhlIGxlZnQgb2YgdGhlIHBsYWNlSG9sZGVyXHJcbiAgICAgIGxldCBsZWZ0ID0gYXJncy5zcGxpY2UoMCwgaSk7XHJcblxyXG4gICAgICAvL3JlbW92ZSB0aGUgcGxhY2VIb2xkZXIgZnJvbSB0aGUgYXJyYXlcclxuICAgICAgYXJncy5zaGlmdCgpO1xyXG5cclxuICAgICAgcmV0dXJuICguLi5jaGlsZHJlbikgPT4gW2xlZnQsIGNoaWxkcmVuLCBhcmdzXTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgcGxhY2Vob2xkZXIsIGRpZCB5b3UgZm9yZ2V0IHRoZSBlMmQucGxhY2VIb2xkZXIoKSBjYWxsPycpO1xyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBjb25jYXQ7XHJcblxuXG4vKioqLyB9LFxuLyogMTkgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xyXG5cclxubGV0IGRyYXdJbWFnZSA9ICguLi5hcmdzKSA9PiB7XHJcbiAgbGV0IFtpbWcsIHN4LCBzeSwgc1dpZHRoLCBzSGVpZ2h0LCBkeCwgZHksIGRXaWR0aCwgZEhlaWdodF0gPSBhcmdzO1xyXG5cclxuICBpZiAoYXJncy5sZW5ndGggPT09IDkpIHtcclxuICAgIHJldHVybiBuZXcgSW5zdHJ1Y3Rpb24oJ2RyYXdJbWFnZVNvdXJjZScsIHtcclxuICAgICAgaW1nLFxyXG4gICAgICBzeCxcclxuICAgICAgc3ksXHJcbiAgICAgIHNXaWR0aCxcclxuICAgICAgc0hlaWdodCxcclxuICAgICAgZHgsXHJcbiAgICAgIGR5LFxyXG4gICAgICBkV2lkdGgsXHJcbiAgICAgIGRIZWlnaHRcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgaWYgKGFyZ3MubGVuZ3RoID49IDUpIHtcclxuICAgIHJldHVybiBuZXcgSW5zdHJ1Y3Rpb24oJ2RyYXdJbWFnZVNpemUnLCB7XHJcbiAgICAgIGltZyxcclxuICAgICAgZHg6IHN4LFxyXG4gICAgICBkeTogc3ksXHJcbiAgICAgIGRXaWR0aDogc1dpZHRoLFxyXG4gICAgICBkSGVpZ2h0OiBzSGVpZ2h0XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGlmIChhcmdzLmxlbmd0aCA+PSAzKSB7XHJcbiAgICByZXR1cm4gbmV3IEluc3RydWN0aW9uKCdkcmF3SW1hZ2UnLCB7XHJcbiAgICAgIGltZyxcclxuICAgICAgZHg6IHN4LFxyXG4gICAgICBkeTogc3lcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG5ldyBJbnN0cnVjdGlvbignZHJhd0ltYWdlJywge1xyXG4gICAgaW1nLFxyXG4gICAgZHg6IDAsXHJcbiAgICBkeTogMFxyXG4gIH0pO1xyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBkcmF3SW1hZ2U7XHJcblxuXG4vKioqLyB9LFxuLyogMjAgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApLFxyXG4gICAgcGkyID0gTWF0aC5QSSAqIDI7XHJcblxyXG5sZXQgZWxsaXBzZSA9ICguLi5hcmdzKSA9PiB7XHJcbiAgbGV0IFt4LCB5LCByYWRpdXNYLCByYWRpdXNZLCByb3RhdGlvbiwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIGFudGljbG9ja3dpc2VdID0gYXJncztcclxuXHJcbiAgbGV0IHByb3BzID0geyB4OiAwLCB5OiAwLCByYWRpdXNYOiB4LCByYWRpdXNZOiB5LCByb3RhdGlvbjogMCwgc3RhcnRBbmdsZTogMCwgZW5kQW5nbGU6IHBpMiwgYW50aWNsb2Nrd2lzZTogZmFsc2UgfTtcclxuXHJcbiAgaWYgKGFyZ3MubGVuZ3RoID4gNSkge1xyXG4gICAgcHJvcHMuc3RhcnRBbmdsZSA9IHN0YXJ0QW5nbGU7XHJcbiAgICBwcm9wcy5lbmRBbmdsZSA9IGVuZEFuZ2xlO1xyXG4gICAgcHJvcHMuYW50aWNsb2Nrd2lzZSA9ICEhYW50aWNsb2Nrd2lzZTtcclxuICB9XHJcblxyXG4gIGlmIChhcmdzLmxlbmd0aCA+IDQpIHtcclxuICAgIHByb3BzLnJvdGF0aW9uID0gcm90YXRpb247XHJcbiAgfVxyXG5cclxuICBpZiAoYXJncy5sZW5ndGggPiAyKXtcclxuICAgIHByb3BzLnggPSB4O1xyXG4gICAgcHJvcHMueSA9IHk7XHJcbiAgICBwcm9wcy5yYWRpdXNYID0gcmFkaXVzWDtcclxuICAgIHByb3BzLnJhZGl1c1kgPSByYWRpdXNZO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG5ldyBJbnN0cnVjdGlvbihcImVsbGlwc2VcIiwgIHByb3BzKTtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZWxsaXBzZTtcclxuXG5cbi8qKiovIH0sXG4vKiAyMSAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBjYWNoZSA9IG5ldyBJbnN0cnVjdGlvbignZmlsbCcpO1xyXG5cclxubGV0IGZpbGwgPSAoKSA9PiBjYWNoZTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZmlsbDtcclxuXG5cbi8qKiovIH0sXG4vKiAyMiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cblxyXG5cclxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKSxcclxuICAgIHBpMiA9IE1hdGguUEkgKiAyO1xyXG5cclxubGV0IGZpbGxBcmMgPSAoLi4uYXJncykgPT4ge1xyXG4gIGxldCBbeCwgeSwgciwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIGNvdW50ZXJjbG9ja3dpc2VdID0gYXJncztcclxuICBsZXQgcHJvcHMgPSB7IHg6IDAsIHk6IDAsIHI6IHgsIHN0YXJ0QW5nbGU6IDAsIGVuZEFuZ2xlOiBwaTIsIGNvdW50ZXJjbG9ja3dpc2U6IGZhbHNlIH07XHJcblxyXG5cclxuICBpZiAoYXJncy5sZW5ndGggPiAzKSB7XHJcbiAgICBwcm9wcy5zdGFydEFuZ2xlID0gc3RhcnRBbmdsZTtcclxuICAgIHByb3BzLmVuZEFuZ2xlID0gZW5kQW5nbGU7XHJcbiAgICBwcm9wcy5jb3VudGVyY2xvY2t3aXNlID0gISFjb3VudGVyY2xvY2t3aXNlO1xyXG4gIH1cclxuXHJcbiAgaWYgKGFyZ3MubGVuZ3RoID49IDIpIHtcclxuICAgIHByb3BzLnggPSB4O1xyXG4gICAgcHJvcHMueSA9IHk7XHJcbiAgICBwcm9wcy5yID0gcjtcclxuICB9XHJcblxyXG4gIHJldHVybiBuZXcgSW5zdHJ1Y3Rpb24oXCJmaWxsQXJjXCIsICBwcm9wcyk7XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZpbGxBcmM7XHJcblxuXG4vKioqLyB9LFxuLyogMjMgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xyXG5cclxubGV0IGZpbGxSZWN0ID0gKC4uLmFyZ3MpID0+IG5ldyBJbnN0cnVjdGlvbignZmlsbFJlY3QnLFxyXG4gIGFyZ3MubGVuZ3RoID4gMiA/XHJcbiAgICB7IHg6IGFyZ3NbMF0sIHk6IGFyZ3NbMV0sIHdpZHRoOiBhcmdzWzJdLCBoZWlnaHQ6IGFyZ3NbM10gfSA6XHJcbiAgICB7IHg6IDAsIHk6IDAsIHdpZHRoOiBhcmdzWzBdLCBoZWlnaHQ6IGFyZ3NbMV0gfVxyXG4pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmaWxsUmVjdDtcclxuXG5cbi8qKiovIH0sXG4vKiAyNCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2VuZEZpbGxTdHlsZScpO1xyXG5cclxubGV0IGZpbGxTdHlsZSA9ICh2YWx1ZSwgLi4uY2hpbGRyZW4pID0+IFtcclxuICAgIG5ldyBJbnN0cnVjdGlvbignZmlsbFN0eWxlJywgeyB2YWx1ZSB9KSxcclxuICAgIGNoaWxkcmVuLFxyXG4gICAgZW5kXHJcbl07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZpbGxTdHlsZTtcclxuXG5cbi8qKiovIH0sXG4vKiAyNSAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgZmlsbFRleHQgPSAoLi4uYXJncykgPT4ge1xyXG4gIGxldCBbdGV4dCwgeCwgeSwgbWF4V2lkdGhdID0gYXJncztcclxuICBpZiAoYXJncy5sZW5ndGggPCA0KSB7XHJcbiAgICBtYXhXaWR0aCA9IG51bGw7XHJcbiAgfVxyXG4gIGlmIChhcmdzLmxlbmd0aCA8IDMpIHtcclxuICAgIHggPSAwO1xyXG4gICAgeSA9IDA7XHJcbiAgfVxyXG4gIHJldHVybiBuZXcgSW5zdHJ1Y3Rpb24oJ2ZpbGxUZXh0JywgeyB0ZXh0LCB4LCB5LCBtYXhXaWR0aCB9KTtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZmlsbFRleHQ7XG5cbi8qKiovIH0sXG4vKiAyNiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cblxyXG5cclxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbignZW5kR2xvYmFsQWxwaGEnKTtcclxuXHJcbmxldCBnbG9iYWxBbHBoYSA9ICh2YWx1ZSwgLi4uY2hpbGRyZW4pID0+IFtcclxuICBuZXcgSW5zdHJ1Y3Rpb24oJ2dsb2JhbEFscGhhJywgeyB2YWx1ZSB9KSxcclxuICBjaGlsZHJlbixcclxuICBlbmRcclxuXTtcclxubW9kdWxlLmV4cG9ydHMgPSBnbG9iYWxBbHBoYTtcclxuXG5cbi8qKiovIH0sXG4vKiAyNyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cblxyXG5cclxudmFyIEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2VuZEdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbicpO1xyXG5cclxubGV0IGdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9ICh2YWx1ZSwgLi4uY2hpbGRyZW4pID0+IFtcclxuICBuZXcgSW5zdHJ1Y3Rpb24oJ2dsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbicsIHsgdmFsdWUgfSksXHJcbiAgY2hpbGRyZW4sXHJcbiAgZW5kXHJcbl07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbjtcclxuXG5cbi8qKiovIH0sXG4vKiAyOCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgaGl0UmVjdCA9IChpZCwgLi4uYXJncykgPT4ge1xyXG4gIGxldCBbeCwgeSwgd2lkdGgsIGhlaWdodF0gPSBhcmdzO1xyXG4gIGlmIChhcmdzLmxlbmd0aCA8PSAzKSB7XHJcbiAgICB3aWR0aCA9IHg7XHJcbiAgICBoZWlnaHQgPSB5O1xyXG4gICAgeCA9IDA7XHJcbiAgICB5ID0gMDtcclxuICB9XHJcbiAgcmV0dXJuIG5ldyBJbnN0cnVjdGlvbignaGl0UmVjdCcsIHtcclxuICAgIGlkLFxyXG4gICAgcG9pbnRzOiBbXHJcbiAgICAgIFt4LCB5XSxcclxuICAgICAgW3ggKyB3aWR0aCwgeSArIGhlaWdodF1cclxuICAgIF1cclxuICB9KTtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gaGl0UmVjdDtcblxuLyoqKi8gfSxcbi8qIDI5ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBoaXRSZWdpb24gPSAoaWQsIHBvaW50cykgPT4gbmV3IEluc3RydWN0aW9uKCdoaXRSZWdpb24nLCB7IGlkLCBwb2ludHMgfSk7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGhpdFJlZ2lvbjtcclxuXG5cbi8qKiovIH0sXG4vKiAzMCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2VuZEltYWdlU21vb3RoaW5nRW5hYmxlZCcpO1xyXG5cclxubGV0IGltYWdlU21vb3RoaW5nRW5hYmxlZCA9ICh2YWx1ZSwgLi4uY2hpbGRyZW4pID0+IFtcclxuICBuZXcgSW5zdHJ1Y3Rpb24oJ2ltYWdlU21vb3RoaW5nRW5hYmxlZCcsIHsgdmFsdWUgfSksXHJcbiAgY2hpbGRyZW4sXHJcbiAgZW5kXHJcbl07XHJcbm1vZHVsZS5leHBvcnRzID0gaW1hZ2VTbW9vdGhpbmdFbmFibGVkO1xyXG5cblxuLyoqKi8gfSxcbi8qIDMxICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IGtleWNvZGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDU2KTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gKGN0eCkgPT4ge1xyXG4gIGxldCB7IGNhbnZhcyB9ID0gY3R4O1xyXG5cclxuICAvL21vdXNlRGF0YVxyXG4gIGNhbnZhc1tTeW1ib2wuZm9yKCdtb3VzZURhdGEnKV0gPSB7XHJcbiAgICB4OiAwLFxyXG4gICAgeTogMCxcclxuICAgIGR4OiAwLFxyXG4gICAgZHk6IDAsXHJcbiAgICBwcmV2aW91c1g6IDAsXHJcbiAgICBwcmV2aW91c1k6IDAsXHJcbiAgICBzdGF0ZTogZmFsc2UsXHJcbiAgICBjbGlja2VkOiAwXHJcbiAgfTtcclxuXHJcbiAgbGV0IGtleXMgPSBjYW52YXNbU3ltYm9sLmZvcigna2V5RGF0YScpXSA9IHt9O1xyXG5cclxuICBmb3IgKGxldCBuYW1lIGluIGtleWNvZGUuY29kZSkge1xyXG4gICAgaWYgKGtleWNvZGUuY29kZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xyXG4gICAgICBrZXlzW25hbWVdID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvL21vdXNlIHJlZ2lvbnNcclxuICBjYW52YXNbU3ltYm9sLmZvcigncmVnaW9ucycpXSA9IFtdO1xyXG4gIGNhbnZhc1tTeW1ib2wuZm9yKCdtb3VzZVBvaW50cycpXSA9IFtdO1xyXG5cclxuICAvL21ha2UgdGhlIGNhbnZhcyByZWNlaXZlIHRvdWNoIGFuZCBtb3VzZSBldmVudHNcclxuICBjYW52YXMudGFiSW5kZXggPSAxO1xyXG5cclxuICBsZXQgbW91c2VNb3ZlID0gKGV2dCkgPT4ge1xyXG4gICAgbGV0IHsgY2xpZW50WCwgY2xpZW50WSB9ID0gZXZ0O1xyXG4gICAgLy9nZXQgbGVmdCBhbmQgdG9wIGNvb3JkaW5hdGVzXHJcbiAgICBsZXQgeyBsZWZ0LCB0b3AgfSA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHJcbiAgICBsZXQgbW91c2VEYXRhID0gY2FudmFzW1N5bWJvbC5mb3IoJ21vdXNlRGF0YScpXTtcclxuXHJcbiAgICBsZXQgcG9pbnQgPSBbY2xpZW50WCAtIGxlZnQsIGNsaWVudFkgLSB0b3AsIG1vdXNlRGF0YS5zdGF0ZV07XHJcblxyXG4gICAgbW91c2VEYXRhLnggPSBwb2ludFswXTtcclxuICAgIG1vdXNlRGF0YS55ID0gcG9pbnRbMV07XHJcblxyXG4gICAgbGV0IHBvaW50cyA9IGNhbnZhc1tTeW1ib2wuZm9yKCdtb3VzZVBvaW50cycpXTtcclxuXHJcbiAgICBwb2ludHMucHVzaChwb2ludCk7XHJcblxyXG4gICAgLy9zdG9yZSB0aGUgbGFzdCAxMDAgc3RvcmVkIHBvc2l0aW9ucyBmb3IgaG92ZXIgZGV0ZWN0aW9uXHJcbiAgICBpZiAocG9pbnRzLmxlbmd0aCA+IDEwMCkge1xyXG4gICAgICBwb2ludHMuc3BsaWNlKDAsIHBvaW50cy5sZW5ndGggLSAxMDApO1xyXG4gICAgfVxyXG5cclxuICAgIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH07XHJcblxyXG4gIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCAoZXZ0KSA9PiBtb3VzZU1vdmUoZXZ0KSk7XHJcbiAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIChldnQpID0+IHtcclxuICAgIGxldCB7IHRhcmdldCB9ID0gZXZ0O1xyXG4gICAgaWYgKHRhcmdldCA9PT0gY2FudmFzKSB7XHJcbiAgICAgIGxldCBtb3VzZURhdGEgPSBjYW52YXNbU3ltYm9sLmZvcignbW91c2VEYXRhJyldO1xyXG5cclxuICAgICAgaWYgKCFtb3VzZURhdGEuc3RhdGUpIHtcclxuICAgICAgICBtb3VzZURhdGEuY2xpY2tlZCArPSAxO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBtb3VzZURhdGEuc3RhdGUgPSB0cnVlO1xyXG4gICAgICByZXR1cm4gbW91c2VNb3ZlKGV2dCk7XHJcbiAgICB9XHJcbiAgfSk7XHJcbiAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCAoZXZ0KSA9PiB7XHJcbiAgICBsZXQgbW91c2VEYXRhID0gY2FudmFzW1N5bWJvbC5mb3IoJ21vdXNlRGF0YScpXTtcclxuICAgIG1vdXNlRGF0YS5zdGF0ZSA9IGZhbHNlO1xyXG4gICAgcmV0dXJuIG1vdXNlTW92ZShldnQpO1xyXG4gIH0pO1xyXG4gIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGV2dCkgPT4ge1xyXG4gICAgY2FudmFzW1N5bWJvbC5mb3IoJ2tleURhdGEnKV1ba2V5Y29kZShldnQua2V5Q29kZSldID0gdHJ1ZTtcclxuICAgIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH0pO1xyXG4gIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIChldnQpID0+IHtcclxuICAgIGNhbnZhc1tTeW1ib2wuZm9yKCdrZXlEYXRhJyldW2tleWNvZGUoZXZ0LmtleUNvZGUpXSA9IGZhbHNlO1xyXG4gICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfSk7XHJcbn07XG5cbi8qKiovIH0sXG4vKiAzMiAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbm1vZHVsZS5leHBvcnRzID0gKGN0eCkgPT4gY3R4LmNhbnZhc1tTeW1ib2wuZm9yKCdrZXlEYXRhJyldO1xuXG4vKioqLyB9LFxuLyogMzMgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xyXG5sZXQgZW5kID0gbmV3IEluc3RydWN0aW9uKCdlbmRMaW5lU3R5bGUnKTtcclxuXHJcbmxldCBsaW5lU3R5bGUgPSAodmFsdWUsIC4uLmNoaWxkcmVuKSA9PiB7XHJcblxyXG4gIHZhbHVlID0gdmFsdWUgfHwge307XHJcbiAgdmFyIHJlc3VsdCA9IHtcclxuICAgIGxpbmVXaWR0aDogbnVsbCxcclxuICAgIGxpbmVDYXA6IG51bGwsXHJcbiAgICBsaW5lSm9pbjogbnVsbCxcclxuICAgIG1pdGVyTGltaXQ6IG51bGwsXHJcbiAgICBsaW5lRGFzaDogbnVsbCxcclxuICAgIGxpbmVEYXNoT2Zmc2V0OiBudWxsXHJcbiAgfTtcclxuXHJcbiAgaWYgKHR5cGVvZiB2YWx1ZS5saW5lV2lkdGggIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICByZXN1bHQubGluZVdpZHRoID0gdmFsdWUubGluZVdpZHRoO1xyXG4gIH1cclxuICBpZiAodHlwZW9mIHZhbHVlLmxpbmVDYXAgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICByZXN1bHQubGluZUNhcCA9IHZhbHVlLmxpbmVDYXA7XHJcbiAgfVxyXG4gIGlmICh0eXBlb2YgdmFsdWUubGluZUpvaW4gIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICByZXN1bHQubGluZUpvaW4gPSB2YWx1ZS5saW5lSm9pbjtcclxuICB9XHJcbiAgaWYgKHR5cGVvZiB2YWx1ZS5taXRlckxpbWl0ICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgcmVzdWx0Lm1pdGVyTGltaXQgPSB2YWx1ZS5taXRlckxpbWl0O1xyXG4gIH1cclxuICBpZiAodHlwZW9mIHZhbHVlLmxpbmVEYXNoICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgcmVzdWx0LmxpbmVEYXNoID0gdmFsdWUubGluZURhc2ggfHwgW107XHJcbiAgfVxyXG4gIGlmICh0eXBlb2YgdmFsdWUubGluZURhc2hPZmZzZXQgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICByZXN1bHQubGluZURhc2hPZmZzZXQgPSB2YWx1ZS5saW5lRGFzaE9mZnNldDtcclxuICB9XHJcbiAgcmV0dXJuIFtcclxuICAgIG5ldyBJbnN0cnVjdGlvbignbGluZVN0eWxlJywgcmVzdWx0KSxcclxuICAgIGNoaWxkcmVuLFxyXG4gICAgZW5kXHJcbiAgXTtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gbGluZVN0eWxlO1xyXG5cblxuLyoqKi8gfSxcbi8qIDM0ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHtcblxubW9kdWxlLmV4cG9ydHMgPSAoY3R4KSA9PiBjdHguY2FudmFzW1N5bWJvbC5mb3IoJ21vdXNlRGF0YScpXTtcblxuLyoqKi8gfSxcbi8qIDM1ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IG1vdmVUbyA9IF9fd2VicGFja19yZXF1aXJlX18oNyksIGxpbmVUbyA9IF9fd2VicGFja19yZXF1aXJlX18oNik7XHJcblxyXG5sZXQgbW92ZVRvTGluZVRvID0gKHBvaW50LCBpbmRleCkgPT4gaW5kZXggPT09IDAgP1xyXG4gIG1vdmVUbyhwb2ludFswXSwgcG9pbnRbMV0pIDpcclxuICBsaW5lVG8ocG9pbnRbMF0sIHBvaW50WzFdKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gbW92ZVRvTGluZVRvO1xyXG5cblxuLyoqKi8gfSxcbi8qIDM2ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IGJlZ2luUGF0aCA9IF9fd2VicGFja19yZXF1aXJlX18oMikoKSxcclxuICAgIGNsb3NlUGF0aCA9IF9fd2VicGFja19yZXF1aXJlX18oMykoKTtcclxuXHJcbmxldCBwYXRoID0gKC4uLmNoaWxkcmVuKSA9PiBbXHJcbiAgYmVnaW5QYXRoLFxyXG4gIGNoaWxkcmVuLFxyXG4gIGNsb3NlUGF0aFxyXG5dO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBwYXRoO1xyXG5cblxuLyoqKi8gfSxcbi8qIDM3ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBjYWNoZSA9IG5ldyBJbnN0cnVjdGlvbigncGxhY2Vob2xkZXInKTtcclxubGV0IHBsYWNlSG9sZGVyID0gKCkgPT4gY2FjaGU7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHBsYWNlSG9sZGVyO1xyXG5cblxuLyoqKi8gfSxcbi8qIDM4ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBxdWFkcmF0aWNDdXJ2ZVRvID0gKGNweCwgY3B5LCB4LCB5KSA9PiBuZXcgSW5zdHJ1Y3Rpb24oJ3F1YWRyYXRpY0N1cnZlVG8nLCB7XHJcbiAgY3B4LFxyXG4gIGNweSxcclxuICB4LFxyXG4gIHlcclxufSk7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHF1YWRyYXRpY0N1cnZlVG87XHJcblxuXG4vKioqLyB9LFxuLyogMzkgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuXG5sZXQgcmFmID0gKGZ1bmMpID0+IHtcclxuICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gcmFmKGZ1bmMpKTtcclxuICByZXR1cm4gZnVuYygpO1xyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSByYWY7XG5cbi8qKiovIH0sXG4vKiA0MCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcblxyXG5sZXQgcmVjdCA9ICguLi5hcmdzKSA9PiBuZXcgSW5zdHJ1Y3Rpb24oJ3JlY3QnLFxyXG4gIGFyZ3MubGVuZ3RoID4gMiA/XHJcbiAgICB7IHg6IGFyZ3NbMF0sIHk6IGFyZ3NbMV0sIHdpZHRoOiBhcmdzWzJdLCBoZWlnaHQ6IGFyZ3NbM10gfSA6XHJcbiAgICB7IHg6IDAsIHk6IDAsIHdpZHRoOiBhcmdzWzBdLCBoZWlnaHQ6IGFyZ3NbMV0gfVxyXG4pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSByZWN0O1xyXG5cblxuLyoqKi8gfSxcbi8qIDQxICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxuXHJcbi8vaW5pdGlhbGl6ZSBhbGwgdGhlIHByb3BlcnRpZXNcclxuXHJcbmxldCBpZGVudGl0eSA9IFsxLCAwLCAwLCAxLCAwLCAwXSxcclxuICBtYXRyaXggPSBuZXcgRmxvYXQ2NEFycmF5KGlkZW50aXR5KSxcclxuICBmaWxsU3R5bGVTdGFjayA9IFtdLFxyXG4gIHN0cm9rZVN0eWxlU3RhY2sgPSBbXSxcclxuICBsaW5lU3R5bGVTdGFjayA9IFtdLFxyXG4gIHRleHRTdHlsZVN0YWNrID0gW10sXHJcbiAgc2hhZG93U3R5bGVTdGFjayA9IFtdLFxyXG4gIGdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvblN0YWNrID0gW10sXHJcbiAgZ2xvYmFsQWxwaGFTdGFjayA9IFtdLFxyXG4gIGltYWdlU21vb3RoaW5nRW5hYmxlZFN0YWNrID0gW10sXHJcbiAgdHJhbnNmb3JtU3RhY2sgPSBuZXcgRmxvYXQ2NEFycmF5KDUwMSAqIDYpLFxyXG4gIHRyYW5zZm9ybVN0YWNrSW5kZXggPSA2LFxyXG4gIGNvbmNhdCA9IFtdLmNvbmNhdCxcclxuICBzdXBwb3J0c0VsbGlwc2UgPSBmYWxzZTtcclxuXHJcbmlmICh0eXBlb2YgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEICE9PSAndW5kZWZpbmVkJykge1xyXG4gIHN1cHBvcnRzRWxsaXBzZSA9IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkoJ2VsbGlwc2UnKTtcclxufVxyXG5cclxuLy90cmFuc2Zvcm0gcG9pbnRzIGZ1bmN0aW9uXHJcbmNvbnN0IHRyYW5zZm9ybVBvaW50cyA9IF9fd2VicGFja19yZXF1aXJlX18oMSk7XHJcbmNvbnN0IGN5Y2xlTW91c2VEYXRhID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0KTtcclxuXHJcbmNvbnN0IGluY3JlYXNlVHJhbnNmb3JtU3RhY2tTaXplID0gKCkgPT4ge1xyXG4gIGxldCBjYWNoZSA9IHRyYW5zZm9ybVN0YWNrO1xyXG4gIHRyYW5zZm9ybVN0YWNrID0gbmV3IEZsb2F0NjRBcnJheSh0cmFuc2Zvcm1TdGFjay5sZW5ndGggKyA2MDApOyAvL2FkZCAxMDAgbW9yZVxyXG4gIHRyYW5zZm9ybVN0YWNrLnNldChjYWNoZSk7XHJcbiAgcmV0dXJuIHRoaXM7XHJcbn07XHJcblxyXG50cmFuc2Zvcm1TdGFjay5zZXQoaWRlbnRpdHkpO1xyXG5cclxuY29uc3QgUEkyID0gTWF0aC5QSSAqIDI7XHJcblxyXG5sZXQgZW1wdHkgPSAodGFyZ2V0KSA9PiB0YXJnZXQgJiYgdGFyZ2V0LnNwbGljZSgwLCB0YXJnZXQubGVuZ3RoKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gKC4uLmFyZ3MpID0+IHtcclxuICBsZXQgY2hpbGRyZW4gPSBhcmdzLnNsaWNlKDAsIC0xKSxcclxuICAgY3R4ID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdO1xyXG5cclxuICBsZXQgcmVnaW9ucyA9IGN0eC5jYW52YXNbU3ltYm9sLmZvcigncmVnaW9ucycpXSxcclxuICAgIG1vdXNlUG9pbnRzID0gY3R4LmNhbnZhc1tTeW1ib2wuZm9yKCdtb3VzZVBvaW50cycpXSxcclxuICAgIGV4dGVuc2lvbnMgPSBjdHguY2FudmFzW1N5bWJvbC5mb3IoJ2V4dGVuc2lvbnMnKV07XHJcblxyXG4gIGxldCBjYWNoZTtcclxuXHJcbiAgY3ljbGVNb3VzZURhdGEoY3R4KTtcclxuXHJcbiAgZW1wdHkocmVnaW9ucyk7XHJcbiAgZW1wdHkobW91c2VQb2ludHMpO1xyXG5cclxuICBsZXQgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xyXG5cclxuICAvL2ZsYXR0ZW4gY2hpbGRyZW4gZHVyaW5nIHRoZSBsb29wIHByb2Nlc3MgdG8gc2F2ZSBjcHVcclxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICBsZXQgY2hpbGQgPSBjaGlsZHJlbltpXTtcclxuXHJcbiAgICAvL2ZsYXR0ZW5pbmcgYWxnb3JpdGhtXHJcbiAgICBpZiAoY2hpbGQgJiYgY2hpbGQuY29uc3RydWN0b3IgPT09IEFycmF5KSB7XHJcbiAgICAgIGNoaWxkcmVuID0gY29uY2F0LmFwcGx5KFtdLCBjaGlsZHJlbik7XHJcbiAgICAgIGNoaWxkID0gY2hpbGRyZW5baV07XHJcblxyXG4gICAgICAvL3JlcGVhdCBhcyBuZWNlc3NhcnlcclxuICAgICAgd2hpbGUgKGNoaWxkICYmIGNoaWxkLmNvbnN0cnVjdG9yID09PSBBcnJheSkge1xyXG4gICAgICAgIGNoaWxkcmVuID0gY29uY2F0LmFwcGx5KFtdLCBjaGlsZHJlbik7XHJcbiAgICAgICAgY2hpbGQgPSBjaGlsZHJlbltpXTtcclxuICAgICAgfVxyXG5cclxuICAgICAgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xyXG4gICAgfVxyXG5cclxuICAgIC8vY2hpbGQgbXVzdCBiZSB0cnV0aHlcclxuICAgIGlmICghY2hpbGQpIHtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHsgcHJvcHMsIHR5cGUgfSA9IGNoaWxkO1xyXG5cclxuICAgIGlmICh0eXBlID09PSAndHJhbnNmb3JtJykge1xyXG5cclxuICAgICAgLy9jb3B5IHRyYW5zZm9ybVN0YWNrIHZhbHVlcyB0byBtYXRyaXhcclxuICAgICAgbWF0cml4WzBdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDZdO1xyXG4gICAgICBtYXRyaXhbMV0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNV07XHJcbiAgICAgIG1hdHJpeFsyXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XTtcclxuICAgICAgbWF0cml4WzNdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdO1xyXG4gICAgICBtYXRyaXhbNF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMl07XHJcbiAgICAgIG1hdHJpeFs1XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXTtcclxuXHJcbiAgICAgIC8vaW5jcmVhc2UgdGhlIGluZGV4XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrSW5kZXggKz0gNjtcclxuICAgICAgaWYgKHRyYW5zZm9ybVN0YWNrSW5kZXggPiB0cmFuc2Zvcm1TdGFjay5sZW5ndGgpIHtcclxuICAgICAgICBpbmNyZWFzZVRyYW5zZm9ybVN0YWNrU2l6ZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvL3BlcmZvcm0gdGhlIHRyYW5zZm9ybSBtYXRoXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA2XSA9IC8vZFxyXG4gICAgICAgIG1hdHJpeFswXSAqIHByb3BzWzBdICsgbWF0cml4WzJdICogcHJvcHNbMV07XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XSA9IC8vYlxyXG4gICAgICAgIG1hdHJpeFsxXSAqIHByb3BzWzBdICsgbWF0cml4WzNdICogcHJvcHNbMV07XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSA9IC8vY1xyXG4gICAgICAgIG1hdHJpeFswXSAqIHByb3BzWzJdICsgbWF0cml4WzJdICogcHJvcHNbM107XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAzXSA9IC8vZFxyXG4gICAgICAgIG1hdHJpeFsxXSAqIHByb3BzWzJdICsgbWF0cml4WzNdICogcHJvcHNbM107XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXSA9IC8vZVxyXG4gICAgICAgIG1hdHJpeFswXSAqIHByb3BzWzRdICsgbWF0cml4WzJdICogcHJvcHNbNV0gKyBtYXRyaXhbNF07XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXSA9IC8vZlxyXG4gICAgICAgIG1hdHJpeFsxXSAqIHByb3BzWzRdICsgbWF0cml4WzNdICogcHJvcHNbNV0gKyBtYXRyaXhbNV07XHJcblxyXG4gICAgICAvL21vZGlmeSB0aGUgY3R4XHJcbiAgICAgIGN0eC5zZXRUcmFuc2Zvcm0oXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDZdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNF0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMV1cclxuICAgICAgKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdzZXRUcmFuc2Zvcm0nKSB7XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrSW5kZXggKz0gNjtcclxuICAgICAgaWYgKHRyYW5zZm9ybVN0YWNrSW5kZXggPiB0cmFuc2Zvcm1TdGFjay5sZW5ndGgpIHtcclxuICAgICAgICBpbmNyZWFzZVRyYW5zZm9ybVN0YWNrU2l6ZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0gPSBwcm9wc1swXTsvL2FcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDVdID0gcHJvcHNbMV07Ly9iXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSA9IHByb3BzWzJdOy8vY1xyXG4gICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM10gPSBwcm9wc1szXTsvL2RcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdID0gcHJvcHNbNF07Ly9lXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXSA9IHByb3BzWzVdOy8vZlxyXG4gICAgICBjdHguc2V0VHJhbnNmb3JtKHByb3BzWzBdLCBwcm9wc1sxXSwgcHJvcHNbMl0sIHByb3BzWzNdLCBwcm9wc1s0XSwgcHJvcHNbNV0pO1xyXG5cclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdzY2FsZScpIHtcclxuICAgICAgbWF0cml4WzBdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDZdO1xyXG4gICAgICBtYXRyaXhbMV0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNV07XHJcbiAgICAgIG1hdHJpeFsyXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XTtcclxuICAgICAgbWF0cml4WzNdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdO1xyXG4gICAgICBtYXRyaXhbNF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMl07XHJcbiAgICAgIG1hdHJpeFs1XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXTtcclxuXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrSW5kZXggKz0gNjtcclxuICAgICAgaWYgKHRyYW5zZm9ybVN0YWNrSW5kZXggPiB0cmFuc2Zvcm1TdGFjay5sZW5ndGgpIHtcclxuICAgICAgICBpbmNyZWFzZVRyYW5zZm9ybVN0YWNrU2l6ZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0gPSBtYXRyaXhbMF0gKiBwcm9wcy54OyAvL2FcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDVdID0gbWF0cml4WzFdICogcHJvcHMueDsgLy9iXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSA9IG1hdHJpeFsyXSAqIHByb3BzLnk7IC8vY1xyXG4gICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM10gPSBtYXRyaXhbM10gKiBwcm9wcy55OyAvL2RcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdID0gbWF0cml4WzRdOyAvL2VcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdID0gbWF0cml4WzVdOyAvL2ZcclxuXHJcbiAgICAgIGN0eC5zZXRUcmFuc2Zvcm0oXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDZdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNF0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMV1cclxuICAgICAgKTtcclxuXHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAndHJhbnNsYXRlJykge1xyXG4gICAgICBtYXRyaXhbMF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl07XHJcbiAgICAgIG1hdHJpeFsxXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XTtcclxuICAgICAgbWF0cml4WzJdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdO1xyXG4gICAgICBtYXRyaXhbM10gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM107XHJcbiAgICAgIG1hdHJpeFs0XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXTtcclxuICAgICAgbWF0cml4WzVdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdO1xyXG5cclxuICAgICAgdHJhbnNmb3JtU3RhY2tJbmRleCArPSA2O1xyXG4gICAgICBpZiAodHJhbnNmb3JtU3RhY2tJbmRleCA+IHRyYW5zZm9ybVN0YWNrLmxlbmd0aCkge1xyXG4gICAgICAgIGluY3JlYXNlVHJhbnNmb3JtU3RhY2tTaXplKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA2XSA9IG1hdHJpeFswXTsgLy9hXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XSA9IG1hdHJpeFsxXTsgLy9iXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSA9IG1hdHJpeFsyXTsgLy9jXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAzXSA9IG1hdHJpeFszXTsgLy9kXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXSA9IG1hdHJpeFs0XSArIG1hdHJpeFswXSAqIHByb3BzLnggKyBtYXRyaXhbMl0gKiBwcm9wcy55OyAvL2VcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdID0gbWF0cml4WzVdICsgbWF0cml4WzFdICogcHJvcHMueCArIG1hdHJpeFszXSAqIHByb3BzLnk7IC8vZlxyXG5cclxuICAgICAgY3R4LnNldFRyYW5zZm9ybShcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDVdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM10sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXVxyXG4gICAgICApO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3JvdGF0ZScpIHtcclxuICAgICAgbWF0cml4WzBdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDZdO1xyXG4gICAgICBtYXRyaXhbMV0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNV07XHJcbiAgICAgIG1hdHJpeFsyXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XTtcclxuICAgICAgbWF0cml4WzNdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdO1xyXG4gICAgICBtYXRyaXhbNF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMl07XHJcbiAgICAgIG1hdHJpeFs1XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXTtcclxuXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrSW5kZXggKz0gNjtcclxuICAgICAgaWYgKHRyYW5zZm9ybVN0YWNrSW5kZXggPiB0cmFuc2Zvcm1TdGFjay5sZW5ndGgpIHtcclxuICAgICAgICBpbmNyZWFzZVRyYW5zZm9ybVN0YWNrU2l6ZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0gPVxyXG4gICAgICAgIG1hdHJpeFswXSAqIHByb3BzLmNvcyArIG1hdHJpeFsyXSAqIHByb3BzLnNpbjsgLy9hXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XSA9XHJcbiAgICAgICAgbWF0cml4WzFdICogcHJvcHMuY29zICsgbWF0cml4WzNdICogcHJvcHMuc2luOyAvL2JcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdID1cclxuICAgICAgICBtYXRyaXhbMF0gKiAtcHJvcHMuc2luICsgbWF0cml4WzJdICogcHJvcHMuY29zOyAvL2NcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdID1cclxuICAgICAgICBtYXRyaXhbMV0gKiAtcHJvcHMuc2luICsgbWF0cml4WzNdICogcHJvcHMuY29zOyAvL2RcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdID0gbWF0cml4WzRdOyAvL2VcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdID0gbWF0cml4WzVdOy8vZlxyXG5cclxuICAgICAgY3R4LnNldFRyYW5zZm9ybShcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDVdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM10sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXVxyXG4gICAgICApO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3NrZXdYJykge1xyXG4gICAgICBtYXRyaXhbMF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl07XHJcbiAgICAgIG1hdHJpeFsxXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XTtcclxuICAgICAgbWF0cml4WzJdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdO1xyXG4gICAgICBtYXRyaXhbM10gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM107XHJcbiAgICAgIG1hdHJpeFs0XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXTtcclxuICAgICAgbWF0cml4WzVdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdO1xyXG5cclxuICAgICAgdHJhbnNmb3JtU3RhY2tJbmRleCArPSA2O1xyXG4gICAgICBpZiAodHJhbnNmb3JtU3RhY2tJbmRleCA+IHRyYW5zZm9ybVN0YWNrLmxlbmd0aCkge1xyXG4gICAgICAgIGluY3JlYXNlVHJhbnNmb3JtU3RhY2tTaXplKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA2XSA9IG1hdHJpeFswXTsgLy9hXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XSA9IG1hdHJpeFsxXTsgLy9iXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSA9IC8vY1xyXG4gICAgICAgIG1hdHJpeFswXSAqIHByb3BzLnggKyBtYXRyaXhbMl07XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAzXSA9IC8vZFxyXG4gICAgICAgIG1hdHJpeFsxXSAqIHByb3BzLnggKyBtYXRyaXhbM107XHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXSA9IG1hdHJpeFs0XTsgLy9lXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXSA9IG1hdHJpeFs1XTsgLy9mXHJcblxyXG5cclxuICAgICAgY3R4LnNldFRyYW5zZm9ybShcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDVdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM10sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXVxyXG4gICAgICApO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3NrZXdZJykge1xyXG4gICAgICBtYXRyaXhbMF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl07XHJcbiAgICAgIG1hdHJpeFsxXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XTtcclxuICAgICAgbWF0cml4WzJdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdO1xyXG4gICAgICBtYXRyaXhbM10gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM107XHJcbiAgICAgIG1hdHJpeFs0XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXTtcclxuICAgICAgbWF0cml4WzVdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdO1xyXG5cclxuICAgICAgdHJhbnNmb3JtU3RhY2tJbmRleCArPSA2O1xyXG4gICAgICBpZiAodHJhbnNmb3JtU3RhY2tJbmRleCA+IHRyYW5zZm9ybVN0YWNrLmxlbmd0aCkge1xyXG4gICAgICAgIGluY3JlYXNlVHJhbnNmb3JtU3RhY2tTaXplKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA2XSA9XHJcbiAgICAgICAgbWF0cml4WzBdICogMSArIG1hdHJpeFsyXSAqIHByb3BzLnk7IC8vYVxyXG4gICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNV0gPVxyXG4gICAgICAgIG1hdHJpeFsxXSAqIDEgKyBtYXRyaXhbM10gKiBwcm9wcy55OyAvL2JcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdID0gbWF0cml4WzJdOyAvL2NcclxuICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDNdID0gbWF0cml4WzNdOyAvL2RcclxuXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXSA9IG1hdHJpeFs0XTsgLy9lXHJcbiAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXSA9IG1hdHJpeFs1XTsgLy9mXHJcblxyXG4gICAgICBjdHguc2V0VHJhbnNmb3JtKFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA2XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNV0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAzXSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMl0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAncmVzdG9yZScpIHtcclxuICAgICAgdHJhbnNmb3JtU3RhY2tJbmRleCAtPSA2O1xyXG4gICAgICBtYXRyaXhbMF0gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl07XHJcbiAgICAgIG1hdHJpeFsxXSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA1XTtcclxuICAgICAgbWF0cml4WzJdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdO1xyXG4gICAgICBtYXRyaXhbM10gPSB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM107XHJcbiAgICAgIG1hdHJpeFs0XSA9IHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAyXTtcclxuICAgICAgbWF0cml4WzVdID0gdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdO1xyXG5cclxuICAgICAgY3R4LnNldFRyYW5zZm9ybShtYXRyaXhbMF0sIG1hdHJpeFsxXSwgbWF0cml4WzJdLCBtYXRyaXhbM10sIG1hdHJpeFs0XSwgbWF0cml4WzVdKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdmaWxsUmVjdCcpIHtcclxuICAgICAgY3R4LmZpbGxSZWN0KHByb3BzLngsIHByb3BzLnksIHByb3BzLndpZHRoLCBwcm9wcy5oZWlnaHQpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3N0cm9rZVJlY3QnKSB7XHJcbiAgICAgIGN0eC5zdHJva2VSZWN0KHByb3BzLngsIHByb3BzLnksIHByb3BzLndpZHRoLCBwcm9wcy5oZWlnaHQpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2NsZWFyUmVjdCcpIHtcclxuICAgICAgY3R4LmNsZWFyUmVjdChwcm9wcy54LCBwcm9wcy55LCBwcm9wcy53aWR0aCwgcHJvcHMuaGVpZ2h0KTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdyZWN0Jykge1xyXG4gICAgICBjdHgucmVjdChwcm9wcy54LCBwcm9wcy55LCBwcm9wcy53aWR0aCwgcHJvcHMuaGVpZ2h0KTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdmaWxsU3R5bGUnKSB7XHJcbiAgICAgIGZpbGxTdHlsZVN0YWNrLnB1c2goY3R4LmZpbGxTdHlsZSk7XHJcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBwcm9wcy52YWx1ZTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdzdHJva2VTdHlsZScpIHtcclxuICAgICAgc3Ryb2tlU3R5bGVTdGFjay5wdXNoKGN0eC5zdHJva2VTdHlsZSk7XHJcbiAgICAgIGN0eC5zdHJva2VTdHlsZSA9IHByb3BzLnZhbHVlO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2VuZEZpbGxTdHlsZScpIHtcclxuICAgICAgY3R4LmZpbGxTdHlsZSA9IGZpbGxTdHlsZVN0YWNrLnBvcCgpO1xyXG5cclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdlbmRTdHJva2VTdHlsZScpIHtcclxuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gc3Ryb2tlU3R5bGVTdGFjay5wb3AoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcbiAgICBpZiAodHlwZSA9PT0gJ2xpbmVTdHlsZScpIHtcclxuICAgICAgbGluZVN0eWxlU3RhY2sucHVzaCh7XHJcbiAgICAgICAgbGluZVdpZHRoOiBjdHgubGluZVdpZHRoLFxyXG4gICAgICAgIGxpbmVDYXA6IGN0eC5saW5lQ2FwLFxyXG4gICAgICAgIGxpbmVKb2luOiBjdHgubGluZUpvaW4sXHJcbiAgICAgICAgbWl0ZXJMaW1pdDogY3R4Lm1pdGVyTGltaXQsXHJcbiAgICAgICAgbGluZURhc2g6IGN0eC5nZXRMaW5lRGFzaCgpLFxyXG4gICAgICAgIGxpbmVEYXNoT2Zmc2V0OiBjdHgubGluZURhc2hPZmZzZXRcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAocHJvcHMubGluZVdpZHRoICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LmxpbmVXaWR0aCA9IHByb3BzLmxpbmVXaWR0aDtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMubGluZUNhcCAhPT0gbnVsbCkge1xyXG4gICAgICAgIGN0eC5saW5lQ2FwID0gcHJvcHMubGluZUNhcDtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMubGluZUpvaW4gIT09IG51bGwpIHtcclxuICAgICAgICBjdHgubGluZUpvaW4gPSBwcm9wcy5saW5lSm9pbjtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMubWl0ZXJMaW1pdCAhPT0gbnVsbCkge1xyXG4gICAgICAgIGN0eC5taXRlckxpbWl0ID0gcHJvcHMubWl0ZXJMaW1pdDtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMubGluZURhc2ggIT09IG51bGwpIHtcclxuICAgICAgICBjdHguc2V0TGluZURhc2gocHJvcHMubGluZURhc2gpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAocHJvcHMubGluZURhc2hPZmZzZXQgIT09IG51bGwpIHtcclxuICAgICAgICBjdHgubGluZURhc2hPZmZzZXQgPSBwcm9wcy5saW5lRGFzaE9mZnNldDtcclxuICAgICAgfVxyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2VuZExpbmVTdHlsZScpIHtcclxuICAgICAgY2FjaGUgPSBsaW5lU3R5bGVTdGFjay5wb3AoKTtcclxuICAgICAgY3R4LmxpbmVXaWR0aCA9IGNhY2hlLmxpbmVXaWR0aDtcclxuICAgICAgY3R4LmxpbmVDYXAgPSBjYWNoZS5saW5lQ2FwO1xyXG4gICAgICBjdHgubGluZUpvaW4gPSBjYWNoZS5saW5lSm9pbjtcclxuICAgICAgY3R4Lm1pdGVyTGltaXQgPSBjYWNoZS5taXRlckxpbWl0O1xyXG4gICAgICBjdHguc2V0TGluZURhc2goY2FjaGUubGluZURhc2gpO1xyXG4gICAgICBjdHgubGluZURhc2hPZmZzZXQgPSBjYWNoZS5saW5lRGFzaE9mZnNldDtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICd0ZXh0U3R5bGUnKSB7XHJcbiAgICAgIHRleHRTdHlsZVN0YWNrLnB1c2goe1xyXG4gICAgICAgIGZvbnQ6IGN0eC5mb250LFxyXG4gICAgICAgIHRleHRBbGlnbjogY3R4LnRleHRBbGlnbixcclxuICAgICAgICB0ZXh0QmFzZWxpbmU6IGN0eC50ZXh0QmFzZWxpbmUsXHJcbiAgICAgICAgZGlyZWN0aW9uOiBjdHguZGlyZWN0aW9uXHJcbiAgICAgIH0pO1xyXG4gICAgICBpZiAocHJvcHMuZm9udCAhPT0gbnVsbCkge1xyXG4gICAgICAgIGN0eC5mb250ID0gcHJvcHMuZm9udDtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMudGV4dEFsaWduICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LnRleHRBbGlnbiA9IHByb3BzLnRleHRBbGlnbjtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMudGV4dEJhc2VsaW5lICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9IHByb3BzLnRleHRCYXNlbGluZTtcclxuICAgICAgfVxyXG4gICAgICBpZiAocHJvcHMuZGlyZWN0aW9uICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LmRpcmVjdGlvbiA9IHByb3BzLmRpcmVjdGlvbjtcclxuICAgICAgfVxyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2VuZFRleHRTdHlsZScpIHtcclxuICAgICAgY2FjaGUgPSB0ZXh0U3R5bGVTdGFjay5wb3AoKTtcclxuICAgICAgY3R4LmZvbnQgPSBjYWNoZS5mb250O1xyXG4gICAgICBjdHgudGV4dEFsaWduID0gY2FjaGUudGV4dEFsaWduO1xyXG4gICAgICBjdHgudGV4dEJhc2VsaW5lID0gY2FjaGUudGV4dEJhc2VsaW5lO1xyXG4gICAgICBjdHguZGlyZWN0aW9uID0gY2FjaGUuZGlyZWN0aW9uO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3NoYWRvd1N0eWxlJykge1xyXG4gICAgICBzaGFkb3dTdHlsZVN0YWNrLnB1c2goe1xyXG4gICAgICAgIHNoYWRvd0JsdXI6IGN0eC5zaGFkb3dCbHVyLFxyXG4gICAgICAgIHNoYWRvd0NvbG9yOiBjdHguc2hhZG93Q29sb3IsXHJcbiAgICAgICAgc2hhZG93T2Zmc2V0WDogY3R4LnNoYWRvd09mZnNldFgsXHJcbiAgICAgICAgc2hhZG93T2Zmc2V0WTogY3R4LnNoYWRvd09mZnNldFlcclxuICAgICAgfSk7XHJcbiAgICAgIGlmIChwcm9wcy5zaGFkb3dCbHVyICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LnNoYWRvd0JsdXIgPSBwcm9wcy5zaGFkb3dCbHVyO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChwcm9wcy5zaGFkb3dDb2xvciAhPT0gbnVsbCkge1xyXG4gICAgICAgIGN0eC5zaGFkb3dDb2xvciA9IHByb3BzLnNoYWRvd0NvbG9yO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChwcm9wcy5zaGFkb3dPZmZzZXRYICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LnNoYWRvd09mZnNldFggPSBwcm9wcy5zaGFkb3dPZmZzZXRYO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChwcm9wcy5zaGFkb3dPZmZzZXRZICE9PSBudWxsKSB7XHJcbiAgICAgICAgY3R4LnNoYWRvd09mZnNldFkgPSBwcm9wcy5zaGFkb3dPZmZzZXRZO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAnZW5kU2hhZG93U3R5bGUnKSB7XHJcbiAgICAgIGNhY2hlID0gc2hhZG93U3R5bGVTdGFjay5wb3AoKTtcclxuICAgICAgY3R4LnNoYWRvd0JsdXIgPSBjYWNoZS5zaGFkb3dCbHVyO1xyXG4gICAgICBjdHguc2hhZG93Q29sb3IgPSBjYWNoZS5zaGFkb3dDb2xvcjtcclxuICAgICAgY3R4LnNoYWRvd09mZnNldFggPSBjYWNoZS5zaGFkb3dPZmZzZXRYO1xyXG4gICAgICBjdHguc2hhZG93T2Zmc2V0WSA9IGNhY2hlLnNoYWRvd09mZnNldFk7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAnc3Ryb2tlVGV4dCcpIHtcclxuICAgICAgaWYgKHByb3BzLm1heFdpZHRoKSB7XHJcbiAgICAgICAgY3R4LnN0cm9rZVRleHQocHJvcHMudGV4dCwgcHJvcHMueCwgcHJvcHMueSwgcHJvcHMubWF4V2lkdGgpO1xyXG4gICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGN0eC5zdHJva2VUZXh0KHByb3BzLnRleHQsIHByb3BzLngsIHByb3BzLnkpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2ZpbGxUZXh0Jykge1xyXG4gICAgICBpZiAocHJvcHMubWF4V2lkdGgpIHtcclxuICAgICAgICBjdHguZmlsbFRleHQocHJvcHMudGV4dCwgcHJvcHMueCwgcHJvcHMueSwgcHJvcHMubWF4V2lkdGgpO1xyXG4gICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGN0eC5maWxsVGV4dChwcm9wcy50ZXh0LCBwcm9wcy54LCBwcm9wcy55KTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdkcmF3SW1hZ2UnKSB7XHJcbiAgICAgIGN0eC5kcmF3SW1hZ2UocHJvcHMuaW1nLCBwcm9wcy5keCwgcHJvcHMuZHkpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2RyYXdJbWFnZVNpemUnKSB7XHJcbiAgICAgIGN0eC5kcmF3SW1hZ2UocHJvcHMuaW1nLCBwcm9wcy5keCwgcHJvcHMuZHksIHByb3BzLmRXaWR0aCwgcHJvcHMuZEhlaWdodCk7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAnZHJhd0ltYWdlU291cmNlJykge1xyXG4gICAgICBjdHguZHJhd0ltYWdlKHByb3BzLmltZywgcHJvcHMuc3gsIHByb3BzLnN5LCBwcm9wcy5zV2lkdGgsIHByb3BzLnNIZWlnaHQsIHByb3BzLmR4LCBwcm9wcy5keSwgcHJvcHMuZFdpZHRoLCBwcm9wcy5kSGVpZ2h0KTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdzdHJva2VBcmMnKSB7XHJcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcclxuICAgICAgY3R4LmFyYyhwcm9wcy54LCBwcm9wcy55LCBwcm9wcy5yLCBwcm9wcy5zdGFydEFuZ2xlLCBwcm9wcy5lbmRBbmdsZSwgcHJvcHMuY291bnRlcmNsb2Nrd2lzZSk7XHJcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcclxuICAgICAgY3R4LnN0cm9rZSgpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2ZpbGxBcmMnKSB7XHJcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcclxuICAgICAgY3R4LmFyYyhwcm9wcy54LCBwcm9wcy55LCBwcm9wcy5yLCBwcm9wcy5zdGFydEFuZ2xlLCBwcm9wcy5lbmRBbmdsZSwgcHJvcHMuY291bnRlcmNsb2Nrd2lzZSk7XHJcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcclxuICAgICAgY3R4LmZpbGwoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdtb3ZlVG8nKSB7XHJcbiAgICAgIGN0eC5tb3ZlVG8ocHJvcHMueCwgcHJvcHMueSk7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAnbGluZVRvJykge1xyXG4gICAgICBjdHgubGluZVRvKHByb3BzLngsIHByb3BzLnkpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2JlemllckN1cnZlVG8nKSB7XHJcbiAgICAgIGN0eC5iZXppZXJDdXJ2ZVRvKHByb3BzLmNwMXgsIHByb3BzLmNwMXksIHByb3BzLmNwMngsIHByb3BzLmNwMnksIHByb3BzLngsIHByb3BzLnkpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3F1YWRyYXRpY0N1cnZlVG8nKSB7XHJcbiAgICAgIGN0eC5xdWFkcmF0aWNDdXJ2ZVRvKHByb3BzLmNweCwgcHJvcHMuY3B5LCBwcm9wcy54LCBwcm9wcy55KTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdhcmMnKSB7XHJcbiAgICAgIGN0eC5hcmMocHJvcHMueCwgcHJvcHMueSwgcHJvcHMuciwgcHJvcHMuc3RhcnRBbmdsZSwgcHJvcHMuZW5kQW5nbGUsIHByb3BzLmNvdW50ZXJjbG9ja3dpc2UpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2FyY1RvJykge1xyXG4gICAgICBjdHguYXJjVG8ocHJvcHMueDEsIHByb3BzLnkxLCBwcm9wcy54MiwgcHJvcHMueTIsIHByb3BzLnIpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2VsbGlwc2UnKSB7XHJcbiAgICAgIC8vaWYgdGhlIG1ldGhvZCBpcyBwcm92aWRlZCBieSB0aGUgYnJvd3NlclxyXG4gICAgICBpZiAoc3VwcG9ydHNFbGxpcHNlKSB7XHJcbiAgICAgICAgY3R4LmVsbGlwc2UoXHJcbiAgICAgICAgICBwcm9wcy54LFxyXG4gICAgICAgICAgcHJvcHMueSxcclxuICAgICAgICAgIHByb3BzLnJhZGl1c1gsXHJcbiAgICAgICAgICBwcm9wcy5yYWRpdXNZLFxyXG4gICAgICAgICAgcHJvcHMucm90YXRpb24sXHJcbiAgICAgICAgICBwcm9wcy5zdGFydEFuZ2xlLFxyXG4gICAgICAgICAgcHJvcHMuZW5kQW5nbGUsXHJcbiAgICAgICAgICBwcm9wcy5hbnRpY2xvY2t3aXNlXHJcbiAgICAgICAgKTtcclxuICAgICAgICBjb250aW51ZTtcclxuICAgICAgfVxyXG4gICAgICBjdHguc2F2ZSgpO1xyXG4gICAgICBjdHgudHJhbnNsYXRlKHByb3BzLngsIHByb3BzLnkpO1xyXG4gICAgICBjdHgucm90YXRlKHByb3BzLnJvdGF0aW9uKTtcclxuICAgICAgY3R4LnNjYWxlKHByb3BzLnJhZGl1c1gsIHByb3BzLnJhZGl1c1kpO1xyXG4gICAgICBjdHguYXJjKDAsIDAsIDEsIHByb3BzLnN0YXJ0QW5nbGUsIHByb3BzLmVuZEFuZ2xlLCBwcm9wcy5hbnRpY2xvY2t3aXNlKTtcclxuICAgICAgY3R4LnJlc3RvcmUoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdnbG9iYWxDb21wb3NpdGVPcGVyYXRpb24nKSB7XHJcbiAgICAgIGdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvblN0YWNrLnB1c2goY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbik7XHJcbiAgICAgIGN0eC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSBwcm9wcy52YWx1ZTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdlbmRHbG9iYWxDb21wb3NpdGVPcGVyYXRpb24nKSB7XHJcbiAgICAgIGN0eC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSBnbG9iYWxDb21wb3NpdGVPcGVyYXRpb25TdGFjay5wb3AoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdmaWxsJykge1xyXG4gICAgICBjdHguZmlsbCgpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ3N0cm9rZScpIHtcclxuICAgICAgY3R4LnN0cm9rZSgpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2JlZ2luQ2xpcCcpIHtcclxuICAgICAgY3R4LnNhdmUoKTtcclxuICAgICAgY3R4LmJlZ2luUGF0aCgpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2NsaXAnKSB7XHJcbiAgICAgIGN0eC5jbGlwKCk7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAnZW5kQ2xpcCcpIHtcclxuICAgICAgY3R4LnJlc3RvcmUoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdiZWdpblBhdGgnKSB7XHJcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdjbG9zZVBhdGgnKSB7XHJcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdnbG9iYWxBbHBoYScpIHtcclxuICAgICAgZ2xvYmFsQWxwaGFTdGFjay5wdXNoKGN0eC5nbG9iYWxBbHBoYSk7XHJcbiAgICAgIGN0eC5nbG9iYWxBbHBoYSAqPSBwcm9wcy52YWx1ZTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdlbmRHbG9iYWxBbHBoYScpIHtcclxuICAgICAgY3R4Lmdsb2JhbEFscGhhID0gZ2xvYmFsQWxwaGFTdGFjay5wb3AoKTtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdoaXRSZWN0JyAmJiByZWdpb25zKSB7XHJcbiAgICAgIGNhY2hlID0gW1xyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA2XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNV0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDRdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAzXSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gMl0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDFdXHJcbiAgICAgIF07XHJcblxyXG4gICAgICByZWdpb25zLnB1c2goe1xyXG4gICAgICAgIGlkOiBwcm9wcy5pZCxcclxuICAgICAgICBwb2ludHM6IHByb3BzLnBvaW50cyxcclxuICAgICAgICBtYXRyaXg6IGNhY2hlLFxyXG4gICAgICAgIC8vcmVjdGFuZ2xlIVxyXG4gICAgICAgIHBvbHlnb246IGZhbHNlLFxyXG4gICAgICAgIGhvdmVyOiBmYWxzZSxcclxuICAgICAgICB0b3VjaGVkOiBmYWxzZSxcclxuICAgICAgICBjbGlja2VkOiBmYWxzZVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2hpdFJlZ2lvbicgJiYgcmVnaW9ucykge1xyXG4gICAgICBjYWNoZSA9IFtcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gNl0sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDVdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSA0XSxcclxuICAgICAgICB0cmFuc2Zvcm1TdGFja1t0cmFuc2Zvcm1TdGFja0luZGV4IC0gM10sXHJcbiAgICAgICAgdHJhbnNmb3JtU3RhY2tbdHJhbnNmb3JtU3RhY2tJbmRleCAtIDJdLFxyXG4gICAgICAgIHRyYW5zZm9ybVN0YWNrW3RyYW5zZm9ybVN0YWNrSW5kZXggLSAxXVxyXG4gICAgICBdO1xyXG5cclxuICAgICAgcmVnaW9ucy5wdXNoKHtcclxuICAgICAgICBpZDogcHJvcHMuaWQsXHJcbiAgICAgICAgcG9pbnRzOiBwcm9wcy5wb2ludHMsXHJcbiAgICAgICAgbWF0cml4OiBjYWNoZSxcclxuICAgICAgICBwb2x5Z29uOiB0cnVlLFxyXG4gICAgICAgIGhvdmVyOiBmYWxzZSxcclxuICAgICAgICB0b3VjaGVkOiBmYWxzZSxcclxuICAgICAgICBjbGlja2VkOiBmYWxzZVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlID09PSAnaW1hZ2VTbW9vdGhpbmdFbmFibGVkJykge1xyXG4gICAgICBpbWFnZVNtb290aGluZ0VuYWJsZWRTdGFjay5wdXNoKGN0eC5pbWFnZVNtb290aGluZ0VuYWJsZWQpO1xyXG4gICAgICBjdHguaW1hZ2VTbW9vdGhpbmdFbmFibGVkID0gcHJvcHMudmFsdWU7XHJcblxyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZSA9PT0gJ2VuZEltYWdlU21vb3RoaW5nRW5hYmxlZCcpIHtcclxuICAgICAgY3R4LmltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGltYWdlU21vb3RoaW5nRW5hYmxlZFN0YWNrLnBvcCgpO1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZXh0ZW5zaW9ucyAmJiBleHRlbnNpb25zW3R5cGVdKSB7XHJcbiAgICAgIGV4dGVuc2lvbnNbdHlwZV0ocHJvcHMsIGN0eCk7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG4gIH1cclxufTtcblxuLyoqKi8gfSxcbi8qIDQyICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IHNldFRyYW5zZm9ybSA9IF9fd2VicGFja19yZXF1aXJlX18oOSk7XHJcblxyXG5sZXQgcmVzZXRUcmFuc2Zvcm0gPSAoLi4uY2hpbGRyZW4pID0+IHNldFRyYW5zZm9ybShbMSwgMCwgMCwgMSwgMCwgMF0sIGNoaWxkcmVuKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gcmVzZXRUcmFuc2Zvcm07XG5cbi8qKiovIH0sXG4vKiA0MyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ3Jlc3RvcmUnKTtcclxuXHJcbmxldCByb3RhdGUgPSAociwgLi4uY2hpbGRyZW4pID0+IFtcclxuICBuZXcgSW5zdHJ1Y3Rpb24oJ3JvdGF0ZScsIHsgY29zOiBNYXRoLmNvcyhyKSwgc2luOiBNYXRoLnNpbihyKSB9KSxcclxuICBjaGlsZHJlbixcclxuICBlbmRcclxuXTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gcm90YXRlO1xyXG5cblxuLyoqKi8gfSxcbi8qIDQ0ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbigncmVzdG9yZScpO1xyXG5cclxubGV0IHNjYWxlID0gKHgsIHksIC4uLmNoaWxkcmVuKSA9PiB7XHJcbiAgaWYgKHR5cGVvZiB5ICE9PSAnbnVtYmVyJykge1xyXG4gICAgY2hpbGRyZW4gPSBbeV0uY29uY2F0KGNoaWxkcmVuKTtcclxuICAgIHkgPSB4O1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIFtcclxuICAgIG5ldyBJbnN0cnVjdGlvbignc2NhbGUnLCB7IHgsIHkgfSksXHJcbiAgICBjaGlsZHJlbixcclxuICAgIGVuZFxyXG4gIF07XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHNjYWxlO1xyXG5cblxuLyoqKi8gfSxcbi8qIDQ1ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbignZW5kU2hhZG93U3R5bGUnKTtcclxuXHJcbmxldCBzaGFkb3dTdHlsZSA9ICh2YWx1ZSwgLi4uY2hpbGRyZW4pID0+IHtcclxuICB2YWx1ZSA9IHZhbHVlIHx8IHt9O1xyXG4gIHZhciByZXN1bHQgPSB7XHJcbiAgICBzaGFkb3dCbHVyOiBudWxsLFxyXG4gICAgc2hhZG93Q29sb3I6IG51bGwsXHJcbiAgICBzaGFkb3dPZmZzZXRYOiBudWxsLFxyXG4gICAgc2hhZG93T2Zmc2V0WTogbnVsbFxyXG4gIH07XHJcblxyXG4gIGlmICh0eXBlb2YgdmFsdWUuc2hhZG93Qmx1ciAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgIHJlc3VsdC5zaGFkb3dCbHVyID0gdmFsdWUuc2hhZG93Qmx1cjtcclxuICB9XHJcbiAgaWYgKHR5cGVvZiB2YWx1ZS5zaGFkb3dDb2xvciAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgIHJlc3VsdC5zaGFkb3dDb2xvciA9IHZhbHVlLnNoYWRvd0NvbG9yO1xyXG4gIH1cclxuICBpZiAodHlwZW9mIHZhbHVlLnNoYWRvd09mZnNldFggIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICByZXN1bHQuc2hhZG93T2Zmc2V0WCA9IHZhbHVlLnNoYWRvd09mZnNldFg7XHJcbiAgfVxyXG4gIGlmICh0eXBlb2YgdmFsdWUuZGlyZWN0aW9uICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgcmVzdWx0LnNoYWRvd09mZnNldFkgPSB2YWx1ZS5zaGFkb3dPZmZzZXRZO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIFtcclxuICAgIG5ldyBJbnN0cnVjdGlvbignc2hhZG93U3R5bGUnLCB2YWx1ZSksXHJcbiAgICBjaGlsZHJlbixcclxuICAgIGVuZFxyXG4gIF07XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHNoYWRvd1N0eWxlO1xyXG5cblxuLyoqKi8gfSxcbi8qIDQ2ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbigncmVzdG9yZScpO1xyXG5cclxubGV0IHNrZXdYID0gKHgsIC4uLmNoaWxkcmVuKSA9PiBbXHJcbiAgbmV3IEluc3RydWN0aW9uKCdza2V3WCcsIHsgeDogTWF0aC50YW4oeCkgfSksXHJcbiAgY2hpbGRyZW4sXHJcbiAgZW5kXHJcbl07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHNrZXdYO1xyXG5cblxuLyoqKi8gfSxcbi8qIDQ3ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbigncmVzdG9yZScpO1xyXG5cclxubGV0IHNrZXdZID0gKHgsIC4uLmNoaWxkcmVuKSA9PiBbXHJcbiAgbmV3IEluc3RydWN0aW9uKCdza2V3WScsIHsgeTogTWF0aC50YW4oeSkgfSksXHJcbiAgY2hpbGRyZW4sXHJcbiAgZW5kXHJcbl07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHNrZXdZO1xyXG5cblxuLyoqKi8gfSxcbi8qIDQ4ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGNhY2hlID0gbmV3IEluc3RydWN0aW9uKCdzdHJva2UnKTtcclxuXHJcbmxldCBzdHJva2UgPSAoKSA9PiBjYWNoZTtcclxubW9kdWxlLmV4cG9ydHMgPSBzdHJva2U7XHJcblxuXG4vKioqLyB9LFxuLyogNDkgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApLFxyXG4gICAgcGkyID0gTWF0aC5QSSAqIDI7XHJcblxyXG5sZXQgc3Ryb2tlQXJjID0gKC4uLmFyZ3MpID0+IHtcclxuICBsZXQgW3gsIHksIHIsIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlLCBjb3VudGVyY2xvY2t3aXNlXSA9IGFyZ3M7XHJcbiAgbGV0IHByb3BzID0geyB4OiAwLCB5OiAwLCByOiB4LCBzdGFydEFuZ2xlOiAwLCBlbmRBbmdsZTogcGkyLCBjb3VudGVyY2xvY2t3aXNlOiBmYWxzZSB9O1xyXG5cclxuXHJcbiAgaWYgKGFyZ3MubGVuZ3RoID4gMykge1xyXG4gICAgcHJvcHMuc3RhcnRBbmdsZSA9IHN0YXJ0QW5nbGU7XHJcbiAgICBwcm9wcy5lbmRBbmdsZSA9IGVuZEFuZ2xlO1xyXG4gICAgcHJvcHMuY291bnRlcmNsb2Nrd2lzZSA9ICEhY291bnRlcmNsb2Nrd2lzZTtcclxuICB9XHJcblxyXG4gIGlmIChhcmdzLmxlbmd0aCA+IDEpe1xyXG4gICAgcHJvcHMueCA9IHg7XHJcbiAgICBwcm9wcy55ID0geTtcclxuICAgIHByb3BzLnIgPSByO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG5ldyBJbnN0cnVjdGlvbihcInN0cm9rZUFyY1wiLCAgcHJvcHMpO1xyXG59O1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBzdHJva2VBcmM7XHJcblxuXG4vKioqLyB9LFxuLyogNTAgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5sZXQgSW5zdHJ1Y3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xyXG5cclxubGV0IHN0cm9rZVJlY3QgPSAoLi4uYXJncykgPT4gbmV3IEluc3RydWN0aW9uKCdzdHJva2VSZWN0JyxcclxuICBhcmdzLmxlbmd0aCA+IDIgP1xyXG4gICAgeyB4OiBhcmdzWzBdLCB5OiBhcmdzWzFdLCB3aWR0aDogYXJnc1syXSwgaGVpZ2h0OiBhcmdzWzNdIH0gOlxyXG4gICAgeyB4OiAwLCB5OiAwLCB3aWR0aDogYXJnc1swXSwgaGVpZ2h0OiBhcmdzWzFdIH1cclxuKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gc3Ryb2tlUmVjdDtcclxuXG5cbi8qKiovIH0sXG4vKiA1MSAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2VuZFN0cm9rZVN0eWxlJyk7XHJcblxyXG5sZXQgc3Ryb2tlU3R5bGUgPSAodmFsdWUsIC4uLmNoaWxkcmVuKSA9PiBbXHJcbiAgbmV3IEluc3RydWN0aW9uKCdzdHJva2VTdHlsZScsIHsgdmFsdWUgfSksXHJcbiAgY2hpbGRyZW4sXHJcbiAgZW5kXHJcbl07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHN0cm9rZVN0eWxlO1xyXG5cblxuLyoqKi8gfSxcbi8qIDUyICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxuXHJcbmxldCBzdHJva2VUZXh0ID0gKC4uLmFyZ3MpID0+IHtcclxuICBsZXQgW3RleHQsIHgsIHksIG1heFdpZHRoXSA9IGFyZ3M7XHJcblxyXG4gIGlmIChhcmdzLmxlbmd0aCA8IDQpIHtcclxuICAgIG1heFdpZHRoID0gbnVsbDtcclxuICB9XHJcbiAgaWYgKGFyZ3MubGVuZ3RoIDwgMykge1xyXG4gICAgeCA9IDA7XHJcbiAgICB5ID0gMDtcclxuICB9XHJcbiAgcmV0dXJuIG5ldyBJbnN0cnVjdGlvbignc3Ryb2tlVGV4dCcsIHtcclxuICAgIHRleHQsXHJcbiAgICB4LFxyXG4gICAgeSxcclxuICAgIG1heFdpZHRoXHJcbiAgfSk7XHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHN0cm9rZVRleHQ7XG5cbi8qKiovIH0sXG4vKiA1MyAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbmxldCBJbnN0cnVjdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oMCk7XHJcbmxldCBlbmQgPSBuZXcgSW5zdHJ1Y3Rpb24oJ2VuZFRleHRTdHlsZScpO1xyXG5cclxubGV0IHRleHRTdHlsZSA9ICh2YWx1ZSwgLi4uY2hpbGRyZW4pID0+IHtcclxuICB2YWx1ZSA9IHZhbHVlIHx8IHt9O1xyXG4gIHZhciByZXN1bHQgPSB7XHJcbiAgICBmb250OiBudWxsLFxyXG4gICAgdGV4dEFsaWduOiBudWxsLFxyXG4gICAgdGV4dEJhc2VsaW5lOiBudWxsLFxyXG4gICAgZGlyZWN0aW9uOiBudWxsXHJcbiAgfTtcclxuXHJcbiAgaWYgKHR5cGVvZiB2YWx1ZS5mb250ICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgcmVzdWx0LmZvbnQgPSB2YWx1ZS5mb250O1xyXG4gIH1cclxuICBpZiAodHlwZW9mIHZhbHVlLnRleHRBbGlnbiAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgIHJlc3VsdC50ZXh0QWxpZ24gPSB2YWx1ZS50ZXh0QWxpZ247XHJcbiAgfVxyXG4gIGlmICh0eXBlb2YgdmFsdWUudGV4dEJhc2VsaW5lICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgcmVzdWx0LnRleHRCYXNlbGluZSA9IHZhbHVlLnRleHRCYXNlbGluZTtcclxuICB9XHJcbiAgaWYgKHR5cGVvZiB2YWx1ZS5kaXJlY3Rpb24gIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICByZXN1bHQuZGlyZWN0aW9uID0gdmFsdWUuZGlyZWN0aW9uO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIFtcclxuICAgIG5ldyBJbnN0cnVjdGlvbigndGV4dFN0eWxlJywgcmVzdWx0KSxcclxuICAgIGNoaWxkcmVuLFxyXG4gICAgZW5kXHJcbiAgXTtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gdGV4dFN0eWxlO1xyXG5cblxuLyoqKi8gfSxcbi8qIDU0ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbigncmVzdG9yZScpO1xyXG5cclxubGV0IHRyYW5zZm9ybSA9ICh2YWx1ZXMsIC4uLmNoaWxkcmVuKSA9PiB7XHJcbiAgcmV0dXJuIFtcclxuICAgIG5ldyBJbnN0cnVjdGlvbigndHJhbnNmb3JtJyxbXHJcbiAgICAgIHZhbHVlc1swXSxcclxuICAgICAgdmFsdWVzWzFdLFxyXG4gICAgICB2YWx1ZXNbMl0sXHJcbiAgICAgIHZhbHVlc1szXSxcclxuICAgICAgdmFsdWVzWzRdLFxyXG4gICAgICB2YWx1ZXNbNV1cclxuICAgIF0pLFxyXG4gICAgY2hpbGRyZW4sXHJcbiAgICBlbmRcclxuICBdO1xyXG59O1xyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gdHJhbnNmb3JtO1xyXG5cblxuLyoqKi8gfSxcbi8qIDU1ICovXG4vKioqLyBmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxubGV0IEluc3RydWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXygwKTtcclxubGV0IGVuZCA9IG5ldyBJbnN0cnVjdGlvbigncmVzdG9yZScpO1xyXG5cclxubGV0IHRyYW5zbGF0ZSA9ICh4LCB5LCAuLi5jaGlsZHJlbikgPT4gW1xyXG4gIG5ldyBJbnN0cnVjdGlvbigndHJhbnNsYXRlJywgeyB4OiB4LCB5OiB5IH0pLFxyXG4gIGNoaWxkcmVuLFxyXG4gIGVuZFxyXG5dO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB0cmFuc2xhdGU7XHJcblxuXG4vKioqLyB9LFxuLyogNTYgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuXG4vLyBTb3VyY2U6IGh0dHA6Ly9qc2ZpZGRsZS5uZXQvdld4OFYvXG4vLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzU2MDMxOTUvZnVsbC1saXN0LW9mLWphdmFzY3JpcHQta2V5Y29kZXNcblxuLyoqXG4gKiBDb25lbmllbmNlIG1ldGhvZCByZXR1cm5zIGNvcnJlc3BvbmRpbmcgdmFsdWUgZm9yIGdpdmVuIGtleU5hbWUgb3Iga2V5Q29kZS5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBrZXlDb2RlIHtOdW1iZXJ9IG9yIGtleU5hbWUge1N0cmluZ31cbiAqIEByZXR1cm4ge01peGVkfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5leHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZWFyY2hJbnB1dCkge1xuICAvLyBLZXlib2FyZCBFdmVudHNcbiAgaWYgKHNlYXJjaElucHV0ICYmICdvYmplY3QnID09PSB0eXBlb2Ygc2VhcmNoSW5wdXQpIHtcbiAgICB2YXIgaGFzS2V5Q29kZSA9IHNlYXJjaElucHV0LndoaWNoIHx8IHNlYXJjaElucHV0LmtleUNvZGUgfHwgc2VhcmNoSW5wdXQuY2hhckNvZGVcbiAgICBpZiAoaGFzS2V5Q29kZSkgc2VhcmNoSW5wdXQgPSBoYXNLZXlDb2RlXG4gIH1cblxuICAvLyBOdW1iZXJzXG4gIGlmICgnbnVtYmVyJyA9PT0gdHlwZW9mIHNlYXJjaElucHV0KSByZXR1cm4gbmFtZXNbc2VhcmNoSW5wdXRdXG5cbiAgLy8gRXZlcnl0aGluZyBlbHNlIChjYXN0IHRvIHN0cmluZylcbiAgdmFyIHNlYXJjaCA9IFN0cmluZyhzZWFyY2hJbnB1dClcblxuICAvLyBjaGVjayBjb2Rlc1xuICB2YXIgZm91bmROYW1lZEtleSA9IGNvZGVzW3NlYXJjaC50b0xvd2VyQ2FzZSgpXVxuICBpZiAoZm91bmROYW1lZEtleSkgcmV0dXJuIGZvdW5kTmFtZWRLZXlcblxuICAvLyBjaGVjayBhbGlhc2VzXG4gIHZhciBmb3VuZE5hbWVkS2V5ID0gYWxpYXNlc1tzZWFyY2gudG9Mb3dlckNhc2UoKV1cbiAgaWYgKGZvdW5kTmFtZWRLZXkpIHJldHVybiBmb3VuZE5hbWVkS2V5XG5cbiAgLy8gd2VpcmQgY2hhcmFjdGVyP1xuICBpZiAoc2VhcmNoLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHNlYXJjaC5jaGFyQ29kZUF0KDApXG5cbiAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG4vKipcbiAqIEdldCBieSBuYW1lXG4gKlxuICogICBleHBvcnRzLmNvZGVbJ2VudGVyJ10gLy8gPT4gMTNcbiAqL1xuXG52YXIgY29kZXMgPSBleHBvcnRzLmNvZGUgPSBleHBvcnRzLmNvZGVzID0ge1xuICAnYmFja3NwYWNlJzogOCxcbiAgJ3RhYic6IDksXG4gICdlbnRlcic6IDEzLFxuICAnc2hpZnQnOiAxNixcbiAgJ2N0cmwnOiAxNyxcbiAgJ2FsdCc6IDE4LFxuICAncGF1c2UvYnJlYWsnOiAxOSxcbiAgJ2NhcHMgbG9jayc6IDIwLFxuICAnZXNjJzogMjcsXG4gICdzcGFjZSc6IDMyLFxuICAncGFnZSB1cCc6IDMzLFxuICAncGFnZSBkb3duJzogMzQsXG4gICdlbmQnOiAzNSxcbiAgJ2hvbWUnOiAzNixcbiAgJ2xlZnQnOiAzNyxcbiAgJ3VwJzogMzgsXG4gICdyaWdodCc6IDM5LFxuICAnZG93bic6IDQwLFxuICAnaW5zZXJ0JzogNDUsXG4gICdkZWxldGUnOiA0NixcbiAgJ2NvbW1hbmQnOiA5MSxcbiAgJ2xlZnQgY29tbWFuZCc6IDkxLFxuICAncmlnaHQgY29tbWFuZCc6IDkzLFxuICAnbnVtcGFkIConOiAxMDYsXG4gICdudW1wYWQgKyc6IDEwNyxcbiAgJ251bXBhZCAtJzogMTA5LFxuICAnbnVtcGFkIC4nOiAxMTAsXG4gICdudW1wYWQgLyc6IDExMSxcbiAgJ251bSBsb2NrJzogMTQ0LFxuICAnc2Nyb2xsIGxvY2snOiAxNDUsXG4gICdteSBjb21wdXRlcic6IDE4MixcbiAgJ215IGNhbGN1bGF0b3InOiAxODMsXG4gICc7JzogMTg2LFxuICAnPSc6IDE4NyxcbiAgJywnOiAxODgsXG4gICctJzogMTg5LFxuICAnLic6IDE5MCxcbiAgJy8nOiAxOTEsXG4gICdgJzogMTkyLFxuICAnWyc6IDIxOSxcbiAgJ1xcXFwnOiAyMjAsXG4gICddJzogMjIxLFxuICBcIidcIjogMjIyXG59XG5cbi8vIEhlbHBlciBhbGlhc2VzXG5cbnZhciBhbGlhc2VzID0gZXhwb3J0cy5hbGlhc2VzID0ge1xuICAnd2luZG93cyc6IDkxLFxuICAn4oenJzogMTYsXG4gICfijKUnOiAxOCxcbiAgJ+KMgyc6IDE3LFxuICAn4oyYJzogOTEsXG4gICdjdGwnOiAxNyxcbiAgJ2NvbnRyb2wnOiAxNyxcbiAgJ29wdGlvbic6IDE4LFxuICAncGF1c2UnOiAxOSxcbiAgJ2JyZWFrJzogMTksXG4gICdjYXBzJzogMjAsXG4gICdyZXR1cm4nOiAxMyxcbiAgJ2VzY2FwZSc6IDI3LFxuICAnc3BjJzogMzIsXG4gICdwZ3VwJzogMzMsXG4gICdwZ2RuJzogMzQsXG4gICdpbnMnOiA0NSxcbiAgJ2RlbCc6IDQ2LFxuICAnY21kJzogOTFcbn1cblxuXG4vKiFcbiAqIFByb2dyYW1hdGljYWxseSBhZGQgdGhlIGZvbGxvd2luZ1xuICovXG5cbi8vIGxvd2VyIGNhc2UgY2hhcnNcbmZvciAoaSA9IDk3OyBpIDwgMTIzOyBpKyspIGNvZGVzW1N0cmluZy5mcm9tQ2hhckNvZGUoaSldID0gaSAtIDMyXG5cbi8vIG51bWJlcnNcbmZvciAodmFyIGkgPSA0ODsgaSA8IDU4OyBpKyspIGNvZGVzW2kgLSA0OF0gPSBpXG5cbi8vIGZ1bmN0aW9uIGtleXNcbmZvciAoaSA9IDE7IGkgPCAxMzsgaSsrKSBjb2Rlc1snZicraV0gPSBpICsgMTExXG5cbi8vIG51bXBhZCBrZXlzXG5mb3IgKGkgPSAwOyBpIDwgMTA7IGkrKykgY29kZXNbJ251bXBhZCAnK2ldID0gaSArIDk2XG5cbi8qKlxuICogR2V0IGJ5IGNvZGVcbiAqXG4gKiAgIGV4cG9ydHMubmFtZVsxM10gLy8gPT4gJ0VudGVyJ1xuICovXG5cbnZhciBuYW1lcyA9IGV4cG9ydHMubmFtZXMgPSBleHBvcnRzLnRpdGxlID0ge30gLy8gdGl0bGUgZm9yIGJhY2t3YXJkIGNvbXBhdFxuXG4vLyBDcmVhdGUgcmV2ZXJzZSBtYXBwaW5nXG5mb3IgKGkgaW4gY29kZXMpIG5hbWVzW2NvZGVzW2ldXSA9IGlcblxuLy8gQWRkIGFsaWFzZXNcbmZvciAodmFyIGFsaWFzIGluIGFsaWFzZXMpIHtcbiAgY29kZXNbYWxpYXNdID0gYWxpYXNlc1thbGlhc11cbn1cblxuXG4vKioqLyB9LFxuLyogNTcgKi9cbi8qKiovIGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwb2ludCwgdnMpIHtcbiAgICAvLyByYXktY2FzdGluZyBhbGdvcml0aG0gYmFzZWQgb25cbiAgICAvLyBodHRwOi8vd3d3LmVjc2UucnBpLmVkdS9Ib21lcGFnZXMvd3JmL1Jlc2VhcmNoL1Nob3J0X05vdGVzL3BucG9seS5odG1sXG4gICAgXG4gICAgdmFyIHggPSBwb2ludFswXSwgeSA9IHBvaW50WzFdO1xuICAgIFxuICAgIHZhciBpbnNpZGUgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMCwgaiA9IHZzLmxlbmd0aCAtIDE7IGkgPCB2cy5sZW5ndGg7IGogPSBpKyspIHtcbiAgICAgICAgdmFyIHhpID0gdnNbaV1bMF0sIHlpID0gdnNbaV1bMV07XG4gICAgICAgIHZhciB4aiA9IHZzW2pdWzBdLCB5aiA9IHZzW2pdWzFdO1xuICAgICAgICBcbiAgICAgICAgdmFyIGludGVyc2VjdCA9ICgoeWkgPiB5KSAhPSAoeWogPiB5KSlcbiAgICAgICAgICAgICYmICh4IDwgKHhqIC0geGkpICogKHkgLSB5aSkgLyAoeWogLSB5aSkgKyB4aSk7XG4gICAgICAgIGlmIChpbnRlcnNlY3QpIGluc2lkZSA9ICFpbnNpZGU7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBpbnNpZGU7XG59O1xuXG5cbi8qKiovIH0sXG4vKiA1OCAqL1xuLyoqKi8gZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAnYWN0aXZlUmVnaW9ucyc6IF9fd2VicGFja19yZXF1aXJlX18oMTApLFxuICAnYXJjJzogX193ZWJwYWNrX3JlcXVpcmVfXygxMSksXG4gICdhcmNUbyc6IF9fd2VicGFja19yZXF1aXJlX18oMTIpLFxuICAnYmVnaW5QYXRoJzogX193ZWJwYWNrX3JlcXVpcmVfXygyKSxcbiAgJ2JlemllckN1cnZlVG8nOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDEzKSxcbiAgJ2NsZWFyUmVjdCc6IF9fd2VicGFja19yZXF1aXJlX18oMTQpLFxuICAnY2xpcCc6IF9fd2VicGFja19yZXF1aXJlX18oMTUpLFxuICAnY2xpcFBhdGgnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDE2KSxcbiAgJ2Nsb3NlUGF0aCc6IF9fd2VicGFja19yZXF1aXJlX18oMyksXG4gICdjcmVhdGVSZWd1bGFyUG9seWdvbic6IF9fd2VicGFja19yZXF1aXJlX18oMTcpLFxuICAnY3JlYXRlV3JhcHBlcic6IF9fd2VicGFja19yZXF1aXJlX18oMTgpLFxuICAnY3ljbGVNb3VzZURhdGEnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDQpLFxuICAnZHJhd0ltYWdlJzogX193ZWJwYWNrX3JlcXVpcmVfXygxOSksXG4gICdlbGxpcHNlJzogX193ZWJwYWNrX3JlcXVpcmVfXygyMCksXG4gICdmaWxsJzogX193ZWJwYWNrX3JlcXVpcmVfXygyMSksXG4gICdmaWxsQXJjJzogX193ZWJwYWNrX3JlcXVpcmVfXygyMiksXG4gICdmaWxsUmVjdCc6IF9fd2VicGFja19yZXF1aXJlX18oMjMpLFxuICAnZmlsbFN0eWxlJzogX193ZWJwYWNrX3JlcXVpcmVfXygyNCksXG4gICdmaWxsVGV4dCc6IF9fd2VicGFja19yZXF1aXJlX18oMjUpLFxuICAnZ2xvYmFsQWxwaGEnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDI2KSxcbiAgJ2dsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbic6IF9fd2VicGFja19yZXF1aXJlX18oMjcpLFxuICAnaGl0UmVjdCc6IF9fd2VicGFja19yZXF1aXJlX18oMjgpLFxuICAnaGl0UmVnaW9uJzogX193ZWJwYWNrX3JlcXVpcmVfXygyOSksXG4gICdpbWFnZVNtb290aGluZ0VuYWJsZWQnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDMwKSxcbiAgJ2luaXRpYWxpemUnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDMxKSxcbiAgJ0luc3RydWN0aW9uJzogX193ZWJwYWNrX3JlcXVpcmVfXygwKSxcbiAgJ2ludmVydE1hdHJpeCc6IF9fd2VicGFja19yZXF1aXJlX18oNSksXG4gICdrZXlEYXRhJzogX193ZWJwYWNrX3JlcXVpcmVfXygzMiksXG4gICdsaW5lU3R5bGUnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDMzKSxcbiAgJ2xpbmVUbyc6IF9fd2VicGFja19yZXF1aXJlX18oNiksXG4gICdtb3VzZURhdGEnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KSxcbiAgJ21vdmVUbyc6IF9fd2VicGFja19yZXF1aXJlX18oNyksXG4gICdtb3ZlVG9MaW5lVG8nOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDM1KSxcbiAgJ3BhdGgnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDM2KSxcbiAgJ3BsYWNlSG9sZGVyJzogX193ZWJwYWNrX3JlcXVpcmVfXygzNyksXG4gICdwb2ludEluUmVjdCc6IF9fd2VicGFja19yZXF1aXJlX18oOCksXG4gICdxdWFkcmF0aWNDdXJ2ZVRvJzogX193ZWJwYWNrX3JlcXVpcmVfXygzOCksXG4gICdyYWYnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDM5KSxcbiAgJ3JlY3QnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDQwKSxcbiAgJ3JlbmRlcic6IF9fd2VicGFja19yZXF1aXJlX18oNDEpLFxuICAncmVzZXRUcmFuc2Zvcm0nOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDQyKSxcbiAgJ3JvdGF0ZSc6IF9fd2VicGFja19yZXF1aXJlX18oNDMpLFxuICAnc2NhbGUnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ0KSxcbiAgJ3NldFRyYW5zZm9ybSc6IF9fd2VicGFja19yZXF1aXJlX18oOSksXG4gICdzaGFkb3dTdHlsZSc6IF9fd2VicGFja19yZXF1aXJlX18oNDUpLFxuICAnc2tld1gnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ2KSxcbiAgJ3NrZXdZJzogX193ZWJwYWNrX3JlcXVpcmVfXyg0NyksXG4gICdzdHJva2UnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ4KSxcbiAgJ3N0cm9rZUFyYyc6IF9fd2VicGFja19yZXF1aXJlX18oNDkpLFxuICAnc3Ryb2tlUmVjdCc6IF9fd2VicGFja19yZXF1aXJlX18oNTApLFxuICAnc3Ryb2tlU3R5bGUnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDUxKSxcbiAgJ3N0cm9rZVRleHQnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDUyKSxcbiAgJ3RleHRTdHlsZSc6IF9fd2VicGFja19yZXF1aXJlX18oNTMpLFxuICAndHJhbnNmb3JtJzogX193ZWJwYWNrX3JlcXVpcmVfXyg1NCksXG4gICd0cmFuc2Zvcm1Qb2ludHMnOiBfX3dlYnBhY2tfcmVxdWlyZV9fKDEpLFxuICAndHJhbnNsYXRlJzogX193ZWJwYWNrX3JlcXVpcmVfXyg1NSlcbn07XG5cbi8qKiovIH1cbi8qKioqKiovIF0pO1xufSk7Il19
const rbush = require( "rbush" );
const ctx = document.createElement( "canvas" ).getContext( "2d" );
const width = ctx.canvas.width = 800;
const height = ctx.canvas.height = 600;
const e2d = require( "e2d" );
document.body.appendChild( ctx.canvas );
const tree = rbush();
const rects = [];
for ( let i = 0; i < 100; i++ ) {
const rectWidth = 10 + Math.random() * 90;
const rectHeight = 10 + Math.random() * 90;
const minX = 0 + Math.random() * ( width - rectWidth );
const minY = 0 + Math.random() * ( height - rectHeight );
const maxX = minX + rectWidth;
const maxY = minY + rectHeight;
const rect = {
rectWidth,
rectHeight,
minX,
minY,
maxX,
maxY,
fill: e2d.fillRect( minX, minY, rectWidth, rectHeight ),
};
rects.push( e2d.strokeRect( minX, minY, rectWidth, rectHeight ) );
tree.insert( rect );
}
e2d.initialize( ctx );
e2d.raf(frame => {
const { x, y } = e2d.mouseData( ctx );
const mouseRect = e2d.fillStyle( "red", e2d.strokeRect( x - 10, y - 10, 20, 20 ) );
e2d.render(
e2d.clearRect( width, height ),
tree.search({
minX: x - 10,
minY: y - 10,
maxX: x + 10,
maxY: y + 10
}).map(z => z.fill),
mouseRect,
rects,
ctx
);
});
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"rbush": "2.0.1",
"e2d": "4.0.0-rc.1"
}
}
<!-- contents of this file will be placed inside the <body> -->
<!-- contents of this file will be placed inside the <head> -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment