webglimpse
Version:
Webglimpse is a data visualization library for the web.
483 lines • 64.1 kB
JavaScript
/*
* Copyright (c) 2014, Metron, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// AA Binary Tree
//
// see: http://user.it.uu.se/~arnea/ps/simp.pdf
// http://en.wikipedia.org/wiki/AA_tree
//
// Tree is self-balancing. Nodes are assigned a level number to assist balancing.
//
// The following invariants hold for AA tree level numbers:
// 1) Leaf node level is 1
// 2) node.left.level = node.level - 1
// 3) node.right.level = node.level or node.right.level = node.level - 1
// 4) grandchild nodes have level less than their grandparents
// 5) every node of level greater than 1 has two children
//
// Requirements 2 and 3 allow "right horizontal links" but not "left horizontal links".
// The "skew" rotation operation turns a left horizontal link that may arise from insertion/deletion into a right horizontal link.
// The" skew" operation might result in two subsequent horizontal links (which is not permitted by requirement 4. This
// condition is fixed by the "splay" rotation operation.
//
// Duplicate values (as determined by the Comparator) are not permitted (insertion of a duplicate value will be ignored).
// Supports O(log n) insertion and deletion and O(1) size retrieval.
//
export class BinaryTree {
constructor(comparator) {
this._root = null;
this._comp = comparator;
this._size = 0;
}
// Inserts the value into the tree. Nothing is inserted if the value already exists
insert(value) {
this._root = this.insert0(value, this._root);
}
// Removes the value from the tree (if it exists)
remove(value) {
this._root = this.remove0(value, this._root);
}
// Removes all values from the tree (size will be 0)
removeAll() {
this._root = null;
this._size = 0;
}
contains(value) {
return this.contains0(value, this._root) !== null;
}
// Gets the actual value stored in the tree or null if it does not exist.
// Normally this is not useful. This method is provided for trees which store additional
// data in their values besides their sort order.
getValue(value) {
return this.contains0(value, this._root);
}
get size() {
return this._size;
}
get isEmpty() {
return (this._size === 0);
}
// Returns the lowest element greater than or equal to the given value, or null if no such element exists
ceiling(value) {
return this.higher0(value, this._root, true);
}
// Returns the greatest element less than or equal to the given value, or null if no such element exists
floor(value) {
return this.lower0(value, this._root, true);
}
// Returns the greatest element strictly less than the given value, or null if no such element exists
lower(value) {
return this.lower0(value, this._root, false);
}
// Returns the lowest element strictly greater than the given value, or null if no such element exists
higher(value) {
return this.higher0(value, this._root, false);
}
// Returns all elements greater than (or equal to, if inclusive is true) the provided value (sorted from low to high)
headSet(value, inclusive = true) {
const results = new Array();
this.head0(value, inclusive, this._root, results);
return results;
}
// Returns all elements less than ( or equal to, if inclusive is true) the provided value (sorted from low to high)
tailSet(value, inclusive = false) {
const results = new Array();
this.tail0(value, inclusive, this._root, results);
return results;
}
// Returns all elements between the provided values (sorted from low to high)
subSet(low, high, lowInclusive = true, highInclusive = false) {
const results = new Array();
this.sub0(low, high, lowInclusive, highInclusive, this._root, results);
return results;
}
// Returns all elements in the tree (sorted from low to high)
toArray() {
const results = new Array();
this.addAll0(this._root, results);
return results;
}
iterator() {
// find the first node by traversing left links down the tree
let node = this._root;
let down;
const stack = new Array();
while (node != null && node.left != null) {
stack.push(node);
node = node.left;
}
down = node.right != null;
return {
next: function () {
const value = node.value;
// down indicates we should follow the right link
if (down && node != null && node.right != null) {
node = node.right;
while (node != null && node.left != null) {
stack.push(node);
node = node.left;
}
down = node.right != null;
}
// up indicates the right link has been followed and we should move up to parent
else {
node = stack.pop();
down = true;
}
return value;
},
hasNext: function () {
return node != null;
}
};
}
compare(node1, node2) {
return this._comp.compare(node1, node2);
}
contains0(value, node) {
if (node == null) {
return null;
}
const comp = this.compare(value, node.value);
if (comp > 0) {
return this.contains0(value, node.right);
}
else if (comp < 0) {
return this.contains0(value, node.left);
}
else {
return node.value;
}
}
lower0(value, node, inclusive) {
if (node == null) {
return null;
}
let comp = this.compare(value, node.value);
let candidate;
if (comp > 0) {
candidate = this.lower0(value, node.right, inclusive);
// don't need to compare again, candidate will be closer to value
return candidate != null ? candidate : node.value;
}
else if (comp < 0 || (!inclusive && comp === 0)) {
// current node's value is lower -- if we don't find a better value:
// * return this node's value if lower
// * otherwise return null
candidate = this.lower0(value, node.left, inclusive);
if (candidate == null) {
candidate = node.value;
}
comp = this.compare(value, candidate);
return comp > 0 || (inclusive && comp === 0) ? candidate : null;
}
else {
// the node's value equals the search value and inclusive is true
return node.value;
}
}
higher0(value, node, inclusive) {
if (node == null) {
return null;
}
let comp = this.compare(value, node.value);
let candidate;
if (comp < 0) {
candidate = this.higher0(value, node.left, inclusive);
// don't need to compare again, candidate will be closer to value
return candidate != null ? candidate : node.value;
}
else if (comp > 0 || (!inclusive && comp === 0)) {
// current node's value is lower -- if we don't find a better value:
// * return this node's value if higher
// * otherwise return null
candidate = this.higher0(value, node.right, inclusive);
if (candidate == null) {
candidate = node.value;
}
comp = this.compare(value, candidate);
return comp < 0 || (inclusive && comp === 0) ? candidate : null;
}
else {
// the node's value equals the search value and inclusive is true
return node.value;
}
}
sub0(low, high, lowInclusive, highInclusive, node, results) {
if (node == null) {
return;
}
// low end of range is above node value
const compLow = this.compare(low, node.value);
if (compLow > 0 || (compLow === 0 && !lowInclusive)) {
return this.sub0(low, high, lowInclusive, highInclusive, node.right, results);
}
// high end of range is below node value
const compHigh = this.compare(high, node.value);
if (compHigh < 0 || (compHigh === 0 && !highInclusive)) {
return this.sub0(low, high, lowInclusive, highInclusive, node.left, results);
}
// value is within range
this.sub0(low, high, lowInclusive, highInclusive, node.left, results);
results.push(node.value);
this.sub0(low, high, lowInclusive, highInclusive, node.right, results);
}
head0(value, inclusive, node, results) {
if (node == null) {
return;
}
const comp = this.compare(value, node.value);
if (comp < 0 || (comp === 0 && inclusive)) {
this.head0(value, inclusive, node.left, results);
results.push(node.value);
this.addAll0(node.right, results);
}
else if (comp > 0) {
this.head0(value, inclusive, node.right, results);
}
}
tail0(value, inclusive, node, results) {
if (node == null) {
return;
}
const comp = this.compare(value, node.value);
if (comp > 0 || (comp === 0 && inclusive)) {
this.addAll0(node.left, results);
results.push(node.value);
this.tail0(value, inclusive, node.right, results);
}
else if (comp < 0) {
this.tail0(value, inclusive, node.left, results);
}
}
addAll0(node, results) {
if (node == null) {
return;
}
this.addAll0(node.left, results);
results.push(node.value);
this.addAll0(node.right, results);
}
// 1) turn deletion of internal node into deletion of leaf node by swapping with closest successor or predecessor
// (which will always be in level 1)
// 2) lower level of nodes whose children are two levels below them (not allowed by invariants 2 and 3)
// also lower level of nodes who are now leaf nodes (level > 1 not allowed by invariant 1)
// 3) skew and split the entire level
remove0(value, node) {
if (node == null) {
return node;
}
// find and remove the node
const comp = this.compare(value, node.value);
if (comp < 0) {
node.left = this.remove0(value, node.left);
}
else if (comp > 0) {
node.right = this.remove0(value, node.right);
}
else {
if (node.isLeaf()) {
return null;
}
else if (node.left == null) {
const lower = node.getSuccessor();
node.right = this.remove0(lower.value, node.right);
node.value = lower.value;
}
else {
const lower = node.getPredecessor();
node.left = this.remove0(lower.value, node.left);
node.value = lower.value;
}
this._size -= 1;
}
// rebalance the tree
node = this.decreaseLevel0(node);
node = this.skew0(node);
node.right = this.skew0(node.right);
if (node.right != null) {
node.right.right = this.skew0(node.right.right);
}
node = this.split0(node);
node.right = this.split0(node.right);
return node;
}
// return the level of the node, or 0 if null
level0(node) {
if (node == null) {
return 0;
}
else {
return node.level;
}
}
// lower the level of nodes which violate invariants 1, 2, and/or 3
decreaseLevel0(node) {
const correctLevel = Math.min(this.level0(node.left), this.level0(node.right)) + 1;
if (correctLevel < node.level) {
node.level = correctLevel;
if (node.right != null && correctLevel < node.right.level) {
node.right.level = correctLevel;
}
}
return node;
}
// 1) insert the value as you would in a binary tree
// 2) walk back to the root performing skew() then split() operations
// returns an updated version of the provided node (after the insert)
insert0(value, node) {
if (node == null) {
this._size += 1;
return this.newTreeNode0(value);
}
// find the appropriate spot and insert the node
const comp = this.compare(value, node.value);
if (comp < 0) {
node.left = this.insert0(value, node.left);
}
else if (comp > 0) {
node.right = this.insert0(value, node.right);
}
// always perform a skew then split to rebalance tree
// (if no balancing is necessary, these operations will return the node unchanged)
node = this.skew0(node);
node = this.split0(node);
return node;
}
newTreeNode0(value) {
return new TreeNode(value);
}
skew0(node) {
if (node == null) {
return null;
}
else if (node.left == null) {
return node;
}
else if (node.left.level === node.level) {
// swap the pointers of the horizontal (same level value) left links
const left = node.left;
node.left = left.right;
left.right = node;
return left;
}
else {
return node;
}
}
split0(node) {
if (node == null) {
return null;
}
else if (node.right == null || node.right.right == null) {
return node;
}
else if (node.level === node.right.right.level) {
// two horizontal (same level value) right links
// take the middle node, elevate it, and return it
const right = node.right;
node.right = right.left;
right.left = node;
right.level = right.level + 1;
return right;
}
else {
return node;
}
}
}
export class TreeNode {
constructor(value, level = 1, left = null, right = null) {
this._level = level;
this._right = right;
this._left = left;
this._value = value;
}
get level() {
return this._level;
}
get right() {
return this._right;
}
get left() {
return this._left;
}
get value() {
return this._value;
}
set right(node) {
this._right = node;
}
set left(node) {
this._left = node;
}
set level(level) {
this._level = level;
}
set value(value) {
this._value = value;
}
isLeaf() {
return this.right == null && this.left == null;
}
getSuccessor() {
let node = this.right;
while (node != null && node.left != null) {
node = node.left;
}
return node;
}
getPredecessor() {
let node = this.left;
while (node != null && node.right != null) {
node = node.right;
}
return node;
}
toString() {
return this.value.toString() + ':' + this.level.toString();
}
}
export class StringComparator {
compare(value1, value2) {
return value1.toLocaleLowerCase().localeCompare(value2.toLocaleLowerCase());
}
}
export class NumberComparator {
compare(value1, value2) {
return value1 - value2;
}
}
export function createStringTree() {
return new BinaryTree(new StringComparator());
}
export function createNumberTree() {
return new BinaryTree(new NumberComparator());
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluYXJ5X3RyZWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd2ViZ2xpbXBzZS91dGlsL2JpbmFyeV90cmVlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBR0gsaUJBQWlCO0FBQ2pCLEVBQUU7QUFDRiwrQ0FBK0M7QUFDL0MsNENBQTRDO0FBQzVDLEVBQUU7QUFDRixpRkFBaUY7QUFDakYsRUFBRTtBQUNGLDJEQUEyRDtBQUMzRCwwQkFBMEI7QUFDMUIsc0NBQXNDO0FBQ3RDLHdFQUF3RTtBQUN4RSw4REFBOEQ7QUFDOUQseURBQXlEO0FBQ3pELEVBQUU7QUFDRix1RkFBdUY7QUFDdkYsa0lBQWtJO0FBQ2xJLHNIQUFzSDtBQUN0SCx3REFBd0Q7QUFDeEQsRUFBRTtBQUNGLHlIQUF5SDtBQUN6SCxvRUFBb0U7QUFDcEUsRUFBRTtBQUNGLE1BQU0sT0FBTyxVQUFVO0lBTW5CLFlBQVksVUFBeUI7UUFDakMsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDbEIsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUM7UUFDeEIsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUVELG1GQUFtRjtJQUNuRixNQUFNLENBQUMsS0FBUTtRQUNYLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRCxpREFBaUQ7SUFDakQsTUFBTSxDQUFDLEtBQVE7UUFDWCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsb0RBQW9EO0lBQ3BELFNBQVM7UUFDTCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUks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RyxNQUFNLENBQUM7SUFDM0IsQ0FBQztDQUNKO0FBRUQsTUFBTSxVQUFVLGdCQUFnQjtJQUM1QixPQUFPLElBQUksVUFBVSxDQUFDLElBQUksZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRCxNQUFNLFVBQVUsZ0JBQWdCO0lBQzVCLE9BQU8sSUFBSSxVQUFVLENBQUMsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7QUFDbEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIENvcHlyaWdodCAoYykgMjAxNCwgTWV0cm9uLCBJbmMuXHJcbiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqXHJcbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXHJcbiAqIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcclxuICpcclxuICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXHJcbiAqICAgIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxyXG4gKlxyXG4gKiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXHJcbiAqICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cclxuICogICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXHJcbiAqXHJcbiAqIDMuIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIGNvcHlyaWdodCBob2xkZXIgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzXHJcbiAqICAgIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0XHJcbiAqICAgIHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi5cclxuICpcclxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXHJcbiAqIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXHJcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcclxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1JcclxuICogQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXHJcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcclxuICogTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OXHJcbiAqIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXHJcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXHJcbiAqIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxyXG4gKi9cclxuXHJcblxyXG4vLyBBQSBCaW5hcnkgVHJlZVxyXG4vL1xyXG4vLyBzZWU6IGh0dHA6Ly91c2VyLml0LnV1LnNlL35hcm5lYS9wcy9zaW1wLnBkZlxyXG4vLyAgICAgIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQUFfdHJlZVxyXG4vL1xyXG4vLyBUcmVlIGlzIHNlbGYtYmFsYW5jaW5nLiBOb2RlcyBhcmUgYXNzaWduZWQgYSBsZXZlbCBudW1iZXIgdG8gYXNzaXN0IGJhbGFuY2luZy5cclxuLy9cclxuLy8gVGhlIGZvbGxvd2luZyBpbnZhcmlhbnRzIGhvbGQgZm9yIEFBIHRyZWUgbGV2ZWwgbnVtYmVyczpcclxuLy8gMSkgTGVhZiBub2RlIGxldmVsIGlzIDFcclxuLy8gMikgbm9kZS5sZWZ0LmxldmVsID0gbm9kZS5sZXZlbCAtIDFcclxuLy8gMykgbm9kZS5yaWdodC5sZXZlbCA9IG5vZGUubGV2ZWwgb3Igbm9kZS5yaWdodC5sZXZlbCA9IG5vZGUubGV2ZWwgLSAxXHJcbi8vIDQpIGdyYW5kY2hpbGQgbm9kZXMgaGF2ZSBsZXZlbCBsZXNzIHRoYW4gdGhlaXIgZ3JhbmRwYXJlbnRzXHJcbi8vIDUpIGV2ZXJ5IG5vZGUgb2YgbGV2ZWwgZ3JlYXRlciB0aGFuIDEgaGFzIHR3byBjaGlsZHJlblxyXG4vL1xyXG4vLyBSZXF1aXJlbWVudHMgMiBhbmQgMyBhbGxvdyBcInJpZ2h0IGhvcml6b250YWwgbGlua3NcIiBidXQgbm90IFwibGVmdCBob3Jpem9udGFsIGxpbmtzXCIuXHJcbi8vIFRoZSBcInNrZXdcIiByb3RhdGlvbiBvcGVyYXRpb24gdHVybnMgYSBsZWZ0IGhvcml6b250YWwgbGluayB0aGF0IG1heSBhcmlzZSBmcm9tIGluc2VydGlvbi9kZWxldGlvbiBpbnRvIGEgcmlnaHQgaG9yaXpvbnRhbCBsaW5rLlxyXG4vLyBUaGVcIiBza2V3XCIgb3BlcmF0aW9uIG1pZ2h0IHJlc3VsdCBpbiB0d28gc3Vic2VxdWVudCBob3Jpem9udGFsIGxpbmtzICh3aGljaCBpcyBub3QgcGVybWl0dGVkIGJ5IHJlcXVpcmVtZW50IDQuIFRoaXNcclxuLy8gY29uZGl0aW9uIGlzIGZpeGVkIGJ5IHRoZSBcInNwbGF5XCIgcm90YXRpb24gb3BlcmF0aW9uLlxyXG4vL1xyXG4vLyBEdXBsaWNhdGUgdmFsdWVzIChhcyBkZXRlcm1pbmVkIGJ5IHRoZSBDb21wYXJhdG9yKSBhcmUgbm90IHBlcm1pdHRlZCAoaW5zZXJ0aW9uIG9mIGEgZHVwbGljYXRlIHZhbHVlIHdpbGwgYmUgaWdub3JlZCkuXHJcbi8vIFN1cHBvcnRzIE8obG9nIG4pIGluc2VydGlvbiBhbmQgZGVsZXRpb24gYW5kIE8oMSkgc2l6ZSByZXRyaWV2YWwuXHJcbi8vXHJcbmV4cG9ydCBjbGFzcyBCaW5hcnlUcmVlPFY+IHtcclxuXHJcbiAgICBwcml2YXRlIF9yb290OiBUcmVlTm9kZTxWPjtcclxuICAgIHByaXZhdGUgX2NvbXA6IENvbXBhcmF0b3I8Vj47XHJcbiAgICBwcml2YXRlIF9zaXplOiBudW1iZXI7XHJcblxyXG4gICAgY29uc3RydWN0b3IoY29tcGFyYXRvcjogQ29tcGFyYXRvcjxWPikge1xyXG4gICAgICAgIHRoaXMuX3Jvb3QgPSBudWxsO1xyXG4gICAgICAgIHRoaXMuX2NvbXAgPSBjb21wYXJhdG9yO1xyXG4gICAgICAgIHRoaXMuX3NpemUgPSAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEluc2VydHMgdGhlIHZhbHVlIGludG8gdGhlIHRyZWUuIE5vdGhpbmcgaXMgaW5zZXJ0ZWQgaWYgdGhlIHZhbHVlIGFscmVhZHkgZXhpc3RzXHJcbiAgICBpbnNlcnQodmFsdWU6IFYpIHtcclxuICAgICAgICB0aGlzLl9yb290ID0gdGhpcy5pbnNlcnQwKHZhbHVlLCB0aGlzLl9yb290KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZW1vdmVzIHRoZSB2YWx1ZSBmcm9tIHRoZSB0cmVlIChpZiBpdCBleGlzdHMpXHJcbiAgICByZW1vdmUodmFsdWU6IFYpIHtcclxuICAgICAgICB0aGlzLl9yb290ID0gdGhpcy5yZW1vdmUwKHZhbHVlLCB0aGlzLl9yb290KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZW1vdmVzIGFsbCB2YWx1ZXMgZnJvbSB0aGUgdHJlZSAoc2l6ZSB3aWxsIGJlIDApXHJcbiAgICByZW1vdmVBbGwoKSB7XHJcbiAgICAgICAgdGhpcy5fcm9vdCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5fc2l6ZSA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgY29udGFpbnModmFsdWU6IFYpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jb250YWluczAodmFsdWUsIHRoaXMuX3Jvb3QpICE9PSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEdldHMgdGhlIGFjdHVhbCB2YWx1ZSBzdG9yZWQgaW4gdGhlIHRyZWUgb3IgbnVsbCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cclxuICAgIC8vIE5vcm1hbGx5IHRoaXMgaXMgbm90IHVzZWZ1bC4gVGhpcyBtZXRob2QgaXMgcHJvdmlkZWQgZm9yIHRyZWVzIHdoaWNoIHN0b3JlIGFkZGl0aW9uYWxcclxuICAgIC8vIGRhdGEgaW4gdGhlaXIgdmFsdWVzIGJlc2lkZXMgdGhlaXIgc29ydCBvcmRlci5cclxuICAgIGdldFZhbHVlKHZhbHVlOiBWKTogViB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbnMwKHZhbHVlLCB0aGlzLl9yb290KTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgc2l6ZSgpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9zaXplO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBpc0VtcHR5KCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAodGhpcy5fc2l6ZSA9PT0gMCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyB0aGUgbG93ZXN0IGVsZW1lbnQgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBnaXZlbiB2YWx1ZSwgb3IgbnVsbCBpZiBubyBzdWNoIGVsZW1lbnQgZXhpc3RzXHJcbiAgICBjZWlsaW5nKHZhbHVlOiBWKTogViB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaGlnaGVyMCh2YWx1ZSwgdGhpcy5fcm9vdCwgdHJ1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyB0aGUgZ3JlYXRlc3QgZWxlbWVudCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIGdpdmVuIHZhbHVlLCBvciBudWxsIGlmIG5vIHN1Y2ggZWxlbWVudCBleGlzdHNcclxuICAgIGZsb29yKHZhbHVlOiBWKTogViB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubG93ZXIwKHZhbHVlLCB0aGlzLl9yb290LCB0cnVlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIHRoZSBncmVhdGVzdCBlbGVtZW50IHN0cmljdGx5IGxlc3MgdGhhbiB0aGUgZ2l2ZW4gdmFsdWUsIG9yIG51bGwgaWYgbm8gc3VjaCBlbGVtZW50IGV4aXN0c1xyXG4gICAgbG93ZXIodmFsdWU6IFYpOiBWIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5sb3dlcjAodmFsdWUsIHRoaXMuX3Jvb3QsIGZhbHNlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIHRoZSBsb3dlc3QgZWxlbWVudCBzdHJpY3RseSBncmVhdGVyIHRoYW4gdGhlIGdpdmVuIHZhbHVlLCBvciBudWxsIGlmIG5vIHN1Y2ggZWxlbWVudCBleGlzdHNcclxuICAgIGhpZ2hlcih2YWx1ZTogVik6IFYge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmhpZ2hlcjAodmFsdWUsIHRoaXMuX3Jvb3QsIGZhbHNlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIGFsbCBlbGVtZW50cyBncmVhdGVyIHRoYW4gKG9yIGVxdWFsIHRvLCBpZiBpbmNsdXNpdmUgaXMgdHJ1ZSkgdGhlIHByb3ZpZGVkIHZhbHVlIChzb3J0ZWQgZnJvbSBsb3cgdG8gaGlnaClcclxuICAgIGhlYWRTZXQodmFsdWU6IFYsIGluY2x1c2l2ZTogYm9vbGVhbiA9IHRydWUpOiBWW10ge1xyXG4gICAgICAgIGNvbnN0IHJlc3VsdHM6IFZbXSA9IG5ldyBBcnJheTxWPigpO1xyXG4gICAgICAgIHRoaXMuaGVhZDAodmFsdWUsIGluY2x1c2l2ZSwgdGhpcy5fcm9vdCwgcmVzdWx0cyk7XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyBhbGwgZWxlbWVudHMgbGVzcyB0aGFuICggb3IgZXF1YWwgdG8sIGlmIGluY2x1c2l2ZSBpcyB0cnVlKSB0aGUgcHJvdmlkZWQgdmFsdWUgKHNvcnRlZCBmcm9tIGxvdyB0byBoaWdoKVxyXG4gICAgdGFpbFNldCh2YWx1ZTogViwgaW5jbHVzaXZlOiBib29sZWFuID0gZmFsc2UpOiBWW10ge1xyXG4gICAgICAgIGNvbnN0IHJlc3VsdHM6IFZbXSA9IG5ldyBBcnJheTxWPigpO1xyXG4gICAgICAgIHRoaXMudGFpbDAodmFsdWUsIGluY2x1c2l2ZSwgdGhpcy5fcm9vdCwgcmVzdWx0cyk7XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyBhbGwgZWxlbWVudHMgYmV0d2VlbiB0aGUgcHJvdmlkZWQgdmFsdWVzIChzb3J0ZWQgZnJvbSBsb3cgdG8gaGlnaClcclxuICAgIHN1YlNldChsb3c6IFYsIGhpZ2g6IFYsIGxvd0luY2x1c2l2ZTogYm9vbGVhbiA9IHRydWUsIGhpZ2hJbmNsdXNpdmU6IGJvb2xlYW4gPSBmYWxzZSk6IFZbXSB7XHJcbiAgICAgICAgY29uc3QgcmVzdWx0czogVltdID0gbmV3IEFycmF5PFY+KCk7XHJcbiAgICAgICAgdGhpcy5zdWIwKGxvdywgaGlnaCwgbG93SW5jbHVzaXZlLCBoaWdoSW5jbHVzaXZlLCB0aGlzLl9yb290LCByZXN1bHRzKTtcclxuICAgICAgICByZXR1cm4gcmVzdWx0cztcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIGFsbCBlbGVtZW50cyBpbiB0aGUgdHJlZSAoc29ydGVkIGZyb20gbG93IHRvIGhpZ2gpXHJcbiAgICB0b0FycmF5KCk6IFZbXSB7XHJcbiAgICAgICAgY29uc3QgcmVzdWx0czogVltdID0gbmV3IEFycmF5PFY+KCk7XHJcbiAgICAgICAgdGhpcy5hZGRBbGwwKHRoaXMuX3Jvb3QsIHJlc3VsdHMpO1xyXG4gICAgICAgIHJldHVybiByZXN1bHRzO1xyXG4gICAgfVxyXG5cclxuICAgIGl0ZXJhdG9yKCk6IEl0ZXJhdG9yPFY+IHtcclxuXHJcbiAgICAgICAgLy8gZmluZCB0aGUgZmlyc3Qgbm9kZSBieSB0cmF2ZXJzaW5nIGxlZnQgbGlua3MgZG93biB0aGUgdHJlZVxyXG4gICAgICAgIGxldCBub2RlOiBUcmVlTm9kZTxWPiA9IHRoaXMuX3Jvb3Q7XHJcbiAgICAgICAgbGV0IGRvd246IGJvb2xlYW47XHJcbiAgICAgICAgY29uc3Qgc3RhY2s6IFRyZWVOb2RlPFY+W10gPSBuZXcgQXJyYXk8VHJlZU5vZGU8Vj4+KCk7XHJcbiAgICAgICAgd2hpbGUgKG5vZGUgIT0gbnVsbCAmJiBub2RlLmxlZnQgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBzdGFjay5wdXNoKG5vZGUpO1xyXG4gICAgICAgICAgICBub2RlID0gbm9kZS5sZWZ0O1xyXG4gICAgICAgIH1cclxuICAgICAgICBkb3duID0gbm9kZS5yaWdodCAhPSBudWxsO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKTogViB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IG5vZGUudmFsdWU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gZG93biBpbmRpY2F0ZXMgd2Ugc2hvdWxkIGZvbGxvdyB0aGUgcmlnaHQgbGlua1xyXG4gICAgICAgICAgICAgICAgaWYgKGRvd24gJiYgbm9kZSAhPSBudWxsICYmIG5vZGUucmlnaHQgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlLnJpZ2h0O1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChub2RlICE9IG51bGwgJiYgbm9kZS5sZWZ0ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhY2sucHVzaChub2RlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUubGVmdDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZG93biA9IG5vZGUucmlnaHQgIT0gbnVsbDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIHVwIGluZGljYXRlcyB0aGUgcmlnaHQgbGluayBoYXMgYmVlbiBmb2xsb3dlZCBhbmQgd2Ugc2hvdWxkIG1vdmUgdXAgdG8gcGFyZW50XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBub2RlID0gc3RhY2sucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZG93biA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBoYXNOZXh0OiBmdW5jdGlvbiAoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZSAhPSBudWxsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBjb21wYXJlKG5vZGUxOiBWLCBub2RlMjogVik6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbXAuY29tcGFyZShub2RlMSwgbm9kZTIpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY29udGFpbnMwKHZhbHVlOiBWLCBub2RlOiBUcmVlTm9kZTxWPik6IFYge1xyXG4gICAgICAgIGlmIChub2RlID09IG51bGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBjb21wOiBudW1iZXIgPSB0aGlzLmNvbXBhcmUodmFsdWUsIG5vZGUudmFsdWUpO1xyXG4gICAgICAgIGlmIChjb21wID4gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluczAodmFsdWUsIG5vZGUucmlnaHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmIChjb21wIDwgMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluczAodmFsdWUsIG5vZGUubGVmdCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gbm9kZS52YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBsb3dlcjAodmFsdWU6IFYsIG5vZGU6IFRyZWVOb2RlPFY+LCBpbmNsdXNpdmU6IGJvb2xlYW4pOiBWIHtcclxuICAgICAgICBpZiAobm9kZSA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGNvbXA6IG51bWJlciA9IHRoaXMuY29tcGFyZSh2YWx1ZSwgbm9kZS52YWx1ZSk7XHJcbiAgICAgICAgbGV0IGNhbmRpZGF0ZTogVjtcclxuICAgICAgICBpZiAoY29tcCA+IDApIHtcclxuICAgICAgICAgICAgY2FuZGlkYXRlID0gdGhpcy5sb3dlcjAodmFsdWUsIG5vZGUucmlnaHQsIGluY2x1c2l2ZSk7XHJcbiAgICAgICAgICAgIC8vIGRvbid0IG5lZWQgdG8gY29tcGFyZSBhZ2FpbiwgY2FuZGlkYXRlIHdpbGwgYmUgY2xvc2VyIHRvIHZhbHVlXHJcbiAgICAgICAgICAgIHJldHVybiBjYW5kaWRhdGUgIT0gbnVsbCA/IGNhbmRpZGF0ZSA6IG5vZGUudmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKGNvbXAgPCAwIHx8ICghaW5jbHVzaXZlICYmIGNvbXAgPT09IDApKSB7XHJcbiAgICAgICAgICAgIC8vIGN1cnJlbnQgbm9kZSdzIHZhbHVlIGlzIGxvd2VyIC0tIGlmIHdlIGRvbid0IGZpbmQgYSBiZXR0ZXIgdmFsdWU6XHJcbiAgICAgICAgICAgIC8vICAgKiByZXR1cm4gdGhpcyBub2RlJ3MgdmFsdWUgaWYgbG93ZXJcclxuICAgICAgICAgICAgLy8gICAqIG90aGVyd2lzZSByZXR1cm4gbnVsbFxyXG4gICAgICAgICAgICBjYW5kaWRhdGUgPSB0aGlzLmxvd2VyMCh2YWx1ZSwgbm9kZS5sZWZ0LCBpbmNsdXNpdmUpO1xyXG4gICAgICAgICAgICBpZiAoY2FuZGlkYXRlID09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZSA9IG5vZGUudmFsdWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29tcCA9IHRoaXMuY29tcGFyZSh2YWx1ZSwgY2FuZGlkYXRlKTtcclxuICAgICAgICAgICAgcmV0dXJuIGNvbXAgPiAwIHx8IChpbmNsdXNpdmUgJiYgY29tcCA9PT0gMCkgPyBjYW5kaWRhdGUgOiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgLy8gdGhlIG5vZGUncyB2YWx1ZSBlcXVhbHMgdGhlIHNlYXJjaCB2YWx1ZSBhbmQgaW5jbHVzaXZlIGlzIHRydWVcclxuICAgICAgICAgICAgcmV0dXJuIG5vZGUudmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgaGlnaGVyMCh2YWx1ZTogViwgbm9kZTogVHJlZU5vZGU8Vj4sIGluY2x1c2l2ZTogYm9vbGVhbik6IFYge1xyXG4gICAgICAgIGlmIChub2RlID09IG51bGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgY29tcDogbnVtYmVyID0gdGhpcy5jb21wYXJlKHZhbHVlLCBub2RlLnZhbHVlKTtcclxuICAgICAgICBsZXQgY2FuZGlkYXRlOiBWO1xyXG4gICAgICAgIGlmIChjb21wIDwgMCkge1xyXG4gICAgICAgICAgICBjYW5kaWRhdGUgPSB0aGlzLmhpZ2hlcjAodmFsdWUsIG5vZGUubGVmdCwgaW5jbHVzaXZlKTtcclxuICAgICAgICAgICAgLy8gZG9uJ3QgbmVlZCB0byBjb21wYXJlIGFnYWluLCBjYW5kaWRhdGUgd2lsbCBiZSBjbG9zZXIgdG8gdmFsdWVcclxuICAgICAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZSAhPSBudWxsID8gY2FuZGlkYXRlIDogbm9kZS52YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoY29tcCA+IDAgfHwgKCFpbmNsdXNpdmUgJiYgY29tcCA9PT0gMCkpIHtcclxuICAgICAgICAgICAgLy8gY3VycmVudCBub2RlJ3MgdmFsdWUgaXMgbG93ZXIgLS0gaWYgd2UgZG9uJ3QgZmluZCBhIGJldHRlciB2YWx1ZTpcclxuICAgICAgICAgICAgLy8gICAqIHJldHVybiB0aGlzIG5vZGUncyB2YWx1ZSBpZiBoaWdoZXJcclxuICAgICAgICAgICAgLy8gICAqIG90aGVyd2lzZSByZXR1cm4gbnVsbFxyXG4gICAgICAgICAgICBjYW5kaWRhdGUgPSB0a