UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

483 lines 64.1 kB
/* * 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