UNPKG

@cute-dw/core

Version:

This TypeScript library is the main part of a more powerfull package designed for the fast WEB software development. The cornerstone of the library is the **DataStore** class, which might be useful when you need a full control of the data, but do not need

168 lines 19.7 kB
import { BinarySearchTree } from "./BinarySearchTree"; /** * In computer science, an `AVL tree` (named after inventors Adelson-Velsky and Landis) is a * self-balancing binary search tree. It was the first such data structure to be invented. * In an AVL tree, the heights of the two child subtrees of any node differ by at most one; * if at any time they differ by more than one, rebalancing is done to restore this property. * Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, * where n is the number of nodes in the tree prior to the operation. Insertions and deletions * may require the tree to be rebalanced by one or more tree rotations. */ export class AvlTree extends BinarySearchTree { /** * @param {K} key * @param {Element} value */ add(key, value) { // Do the normal BST insert. const node = super.add(key, value); // Let's move up to the root and check balance factors along the way. let currentNode = node; while (currentNode) { this.balance(currentNode); currentNode = currentNode.parent; } return node; } /** * @param {K} key * @return {boolean} */ remove(key) { if (this.root) { // Do standard BST removal. const removedElement = super.remove(key); if (removedElement) { // Balance the tree starting from the root node. this.balance(this.root); } return removedElement; } return undefined; } /** * @param {BinaryTreeNode} node */ balance(node) { if (!node) return; // If balance factor is not OK then try to balance the node. if (node.balanceFactor > 1 && node.left) { // Left rotation. if (node.left.balanceFactor > 0) { // Left-Left rotation this.rotateLeftLeft(node); } else if (node.left.balanceFactor < 0) { // Left-Right rotation. this.rotateLeftRight(node); } } else if (node.balanceFactor < -1 && node.right) { // Right rotation. if (node.right.balanceFactor < 0) { // Right-Right rotation this.rotateRightRight(node); } else if (node.right.balanceFactor > 0) { // Right-Left rotation. this.rotateRightLeft(node); } } } /** * @param {BinaryTreeNode} rootNode */ rotateLeftLeft(rootNode) { // Detach left node from root node. const leftNode = rootNode.left; rootNode.setLeft(null); // Make left node to be a child of rootNode's parent. if (rootNode.parent) { rootNode.parent.setRight(leftNode); } else if (rootNode === this.root) { // If root node is root then make left node to be a new root. this.root = leftNode; } // If left node has a right child then detach it and // attach it as a left child for rootNode. const leftRightNode = leftNode.right; // Attach rootNode to the right of leftNode. leftNode.setRight(rootNode); if (leftRightNode) { rootNode.setLeft(leftRightNode); } } /** * @param {BinaryTreeNode} rootNode */ rotateLeftRight(rootNode) { // Detach left node from rootNode since it is going to be replaced. const leftNode = rootNode.left; rootNode.setLeft(null); // Detach right node from leftNode. const leftRightNode = leftNode.right; leftNode.setRight(null); if (leftRightNode && leftRightNode.left) { // Preserve leftRightNode's left subtree. leftNode.setRight(leftRightNode.left); // Attach leftNode as left node for leftRight node. leftRightNode.setLeft(null); } // Attach leftRightNode to the rootNode. rootNode.setLeft(leftRightNode); // Do left-left rotation. this.rotateLeftLeft(rootNode); } /** * @param {BinaryTreeNode} rootNode */ rotateRightLeft(rootNode) { // Detach right node from rootNode since it is going to be replaced. const rightNode = rootNode.right; rootNode.setRight(null); // Detach left node from rightNode. const rightLeftNode = rightNode.left; rightNode.setLeft(null); if (rightLeftNode) { if (rightLeftNode.right) { rightNode.setLeft(rightLeftNode.right); //rightLeftNode.setRight(null); } // Attach rightNode as right node for rightLeft node. rightLeftNode.setRight(rightNode); } // Attach rightLeftNode to the rootNode. rootNode.setRight(rightLeftNode); // Attach rightNode as right node for rightLeft node. //rightLeftNode!.setRight(rightNode); // Do right-right rotation. this.rotateRightRight(rootNode); } /** * @param {BinaryTreeNode} rootNode */ rotateRightRight(rootNode) { // Detach right node from root node. const rightNode = rootNode.right; rootNode.setRight(null); // Make right node to be a child of rootNode's parent. if (rootNode.parent) { rootNode.parent.setLeft(rightNode); } else if (rootNode === this.root) { // If root node is root then make right node to be a new root. this.root = rightNode; } // If right node has a left child then detach it and // attach it as a right child for rootNode. const rightLeftNode = rightNode.left; // Attach rootNode to the left of rightNode. rightNode.setLeft(rootNode); if (rightLeftNode) { rootNode.setRight(rightLeftNode); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXZsVHJlZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2N1dGUtY29yZS9zcmMvbGliL2NvbGxlY3Rpb25zL3RyZWUvQXZsVHJlZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUl0RDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sT0FBTyxPQUFnQixTQUFRLGdCQUFzQjtJQUV6RDs7O09BR0c7SUFDSCxHQUFHLENBQUMsR0FBTSxFQUFFLEtBQWlCO1FBQzNCLDRCQUE0QjtRQUM1QixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUVuQyxxRUFBcUU7UUFDckUsSUFBSSxXQUFXLEdBQWdDLElBQUksQ0FBQztRQUNwRCxPQUFPLFdBQVcsRUFBRTtZQUNsQixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQzFCLFdBQVcsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDO1NBQ2xDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0Q7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLEdBQU07UUFDWCxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDYiwyQkFBMkI7WUFDM0IsTUFBTSxjQUFjLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6QyxJQUFJLGNBQWMsRUFBRTtnQkFDbEIsZ0RBQWdEO2dCQUNoRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN6QjtZQUNELE9BQU8sY0FBYyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNEOztPQUVHO0lBQ0ssT0FBTyxDQUFDLElBQTBCO1FBQ3hDLElBQUksQ0FBQyxJQUFJO1lBQUUsT0FBTztR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LFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUNsQztJQUVILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJpbmFyeVNlYXJjaFRyZWUgfSBmcm9tIFwiLi9CaW5hcnlTZWFyY2hUcmVlXCI7XHJcbmltcG9ydCB7IEVsZW1lbnQgfSBmcm9tIFwiLi4vQ29sbGVjdGlvblwiO1xyXG5pbXBvcnQgeyBCaW5hcnlUcmVlTm9kZSB9IGZyb20gXCIuL0JpbmFyeVRyZWVOb2RlXCI7XHJcblxyXG4vKipcclxuICogSW4gY29tcHV0ZXIgc2NpZW5jZSwgYW4gYEFWTCB0cmVlYCAobmFtZWQgYWZ0ZXIgaW52ZW50b3JzIEFkZWxzb24tVmVsc2t5IGFuZCBMYW5kaXMpIGlzIGFcclxuICogc2VsZi1iYWxhbmNpbmcgYmluYXJ5IHNlYXJjaCB0cmVlLiBJdCB3YXMgdGhlIGZpcnN0IHN1Y2ggZGF0YSBzdHJ1Y3R1cmUgdG8gYmUgaW52ZW50ZWQuXHJcbiAqIEluIGFuIEFWTCB0cmVlLCB0aGUgaGVpZ2h0cyBvZiB0aGUgdHdvIGNoaWxkIHN1YnRyZWVzIG9mIGFueSBub2RlIGRpZmZlciBieSBhdCBtb3N0IG9uZTtcclxuICogaWYgYXQgYW55IHRpbWUgdGhleSBkaWZmZXIgYnkgbW9yZSB0aGFuIG9uZSwgcmViYWxhbmNpbmcgaXMgZG9uZSB0byByZXN0b3JlIHRoaXMgcHJvcGVydHkuXHJcbiAqIExvb2t1cCwgaW5zZXJ0aW9uLCBhbmQgZGVsZXRpb24gYWxsIHRha2UgTyhsb2cgbikgdGltZSBpbiBib3RoIHRoZSBhdmVyYWdlIGFuZCB3b3JzdCBjYXNlcyxcclxuICogd2hlcmUgbiBpcyB0aGUgbnVtYmVyIG9mIG5vZGVzIGluIHRoZSB0cmVlIHByaW9yIHRvIHRoZSBvcGVyYXRpb24uIEluc2VydGlvbnMgYW5kIGRlbGV0aW9uc1xyXG4gKiBtYXkgcmVxdWlyZSB0aGUgdHJlZSB0byBiZSByZWJhbGFuY2VkIGJ5IG9uZSBvciBtb3JlIHRyZWUgcm90YXRpb25zLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEF2bFRyZWU8SywgVj1LPiBleHRlbmRzIEJpbmFyeVNlYXJjaFRyZWU8SywgVj4ge1xyXG5cclxuICAvKipcclxuICAgKiBAcGFyYW0ge0t9IGtleVxyXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gdmFsdWVcclxuICAgKi9cclxuICBhZGQoa2V5OiBLLCB2YWx1ZTogRWxlbWVudDxWPik6IEJpbmFyeVRyZWVOb2RlPEssIFY+IHtcclxuICAgIC8vIERvIHRoZSBub3JtYWwgQlNUIGluc2VydC5cclxuICAgIGNvbnN0IG5vZGUgPSBzdXBlci5hZGQoa2V5LCB2YWx1ZSk7XHJcblxyXG4gICAgLy8gTGV0J3MgbW92ZSB1cCB0byB0aGUgcm9vdCBhbmQgY2hlY2sgYmFsYW5jZSBmYWN0b3JzIGFsb25nIHRoZSB3YXkuXHJcbiAgICBsZXQgY3VycmVudE5vZGU6IEJpbmFyeVRyZWVOb2RlPEssIFY+IHwgbnVsbCA9IG5vZGU7XHJcbiAgICB3aGlsZSAoY3VycmVudE5vZGUpIHtcclxuICAgICAgdGhpcy5iYWxhbmNlKGN1cnJlbnROb2RlKTtcclxuICAgICAgY3VycmVudE5vZGUgPSBjdXJyZW50Tm9kZS5wYXJlbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5vZGU7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBwYXJhbSB7S30ga2V5XHJcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cclxuICAgKi9cclxuICByZW1vdmUoa2V5OiBLKTogRWxlbWVudDxWPiB8IHVuZGVmaW5lZCB7XHJcbiAgICBpZiAodGhpcy5yb290KSB7XHJcbiAgICAgIC8vIERvIHN0YW5kYXJkIEJTVCByZW1vdmFsLlxyXG4gICAgICBjb25zdCByZW1vdmVkRWxlbWVudCA9IHN1cGVyLnJlbW92ZShrZXkpO1xyXG4gICAgICBpZiAocmVtb3ZlZEVsZW1lbnQpIHtcclxuICAgICAgICAvLyBCYWxhbmNlIHRoZSB0cmVlIHN0YXJ0aW5nIGZyb20gdGhlIHJvb3Qgbm9kZS5cclxuICAgICAgICB0aGlzLmJhbGFuY2UodGhpcy5yb290KTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gcmVtb3ZlZEVsZW1lbnQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAcGFyYW0ge0JpbmFyeVRyZWVOb2RlfSBub2RlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBiYWxhbmNlKG5vZGU6IEJpbmFyeVRyZWVOb2RlPEssIFY+KTogdm9pZCB7XHJcbiAgICBpZiAoIW5vZGUpIHJldHVybjtcclxuICAgIC8vIElmIGJhbGFuY2UgZmFjdG9yIGlzIG5vdCBPSyB0aGVuIHRyeSB0byBiYWxhbmNlIHRoZSBub2RlLlxyXG4gICAgaWYgKG5vZGUuYmFsYW5jZUZhY3RvciA+IDEgJiYgbm9kZS5sZWZ0KSB7XHJcbiAgICAgIC8vIExlZnQgcm90YXRpb24uXHJcbiAgICAgIGlmIChub2RlLmxlZnQuYmFsYW5jZUZhY3RvciA+IDApIHtcclxuICAgICAgICAvLyBMZWZ0LUxlZnQgcm90YXRpb25cclxuICAgICAgICB0aGlzLnJvdGF0ZUxlZnRMZWZ0KG5vZGUpO1xyXG4gICAgICB9IGVsc2UgaWYgKG5vZGUubGVmdC5iYWxhbmNlRmFjdG9yIDwgMCkge1xyXG4gICAgICAgIC8vIExlZnQtUmlnaHQgcm90YXRpb24uXHJcbiAgICAgICAgdGhpcy5yb3RhdGVMZWZ0UmlnaHQobm9kZSk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZiAobm9kZS5iYWxhbmNlRmFjdG9yIDwgLTEgJiYgbm9kZS5yaWdodCkge1xyXG4gICAgICAvLyBSaWdodCByb3RhdGlvbi5cclxuICAgICAgaWYgKG5vZGUucmlnaHQuYmFsYW5jZUZhY3RvciA8IDApIHtcclxuICAgICAgICAvLyBSaWdodC1SaWdodCByb3RhdGlvblxyXG4gICAgICAgIHRoaXMucm90YXRlUmlnaHRSaWdodChub2RlKTtcclxuICAgICAgfSBlbHNlIGlmIChub2RlLnJpZ2h0LmJhbGFuY2VGYWN0b3IgPiAwKSB7XHJcbiAgICAgICAgLy8gUmlnaHQtTGVmdCByb3RhdGlvbi5cclxuICAgICAgICB0aGlzLnJvdGF0ZVJpZ2h0TGVmdChub2RlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBAcGFyYW0ge0JpbmFyeVRyZWVOb2RlfSByb290Tm9kZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgcm90YXRlTGVmdExlZnQocm9vdE5vZGU6IEJpbmFyeVRyZWVOb2RlPEssIFY+KTogdm9pZCB7XHJcbiAgICAvLyBEZXRhY2ggbGVmdCBub2RlIGZyb20gcm9vdCBub2RlLlxyXG4gICAgY29uc3QgbGVmdE5vZGUgPSByb290Tm9kZS5sZWZ0IGFzIEJpbmFyeVRyZWVOb2RlPEssIFY+O1xyXG4gICAgcm9vdE5vZGUuc2V0TGVmdChudWxsKTtcclxuXHJcbiAgICAvLyBNYWtlIGxlZnQgbm9kZSB0byBiZSBhIGNoaWxkIG9mIHJvb3ROb2RlJ3MgcGFyZW50LlxyXG4gICAgaWYgKHJvb3ROb2RlLnBhcmVudCkge1xyXG4gICAgICByb290Tm9kZS5wYXJlbnQuc2V0UmlnaHQobGVmdE5vZGUpO1xyXG4gICAgfSBlbHNlIGlmIChyb290Tm9kZSA9PT0gdGhpcy5yb290KSB7XHJcbiAgICAgIC8vIElmIHJvb3Qgbm9kZSBpcyByb290IHRoZW4gbWFrZSBsZWZ0IG5vZGUgdG8gYmUgYSBuZXcgcm9vdC5cclxuICAgICAgdGhpcy5yb290ID0gbGVmdE5vZGU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gSWYgbGVmdCBub2RlIGhhcyBhIHJpZ2h0IGNoaWxkIHRoZW4gZGV0YWNoIGl0IGFuZFxyXG4gICAgLy8gYXR0YWNoIGl0IGFzIGEgbGVmdCBjaGlsZCBmb3Igcm9vdE5vZGUuXHJcbiAgICBjb25zdCBsZWZ0UmlnaHROb2RlID0gbGVmdE5vZGUucmlnaHQ7XHJcblxyXG4gICAgLy8gQXR0YWNoIHJvb3ROb2RlIHRvIHRoZSByaWdodCBvZiBsZWZ0Tm9kZS5cclxuICAgIGxlZnROb2RlLnNldFJpZ2h0KHJvb3ROb2RlKTtcclxuXHJcbiAgICBpZiAobGVmdFJpZ2h0Tm9kZSkge1xyXG4gICAgICByb290Tm9kZS5zZXRMZWZ0KGxlZnRSaWdodE5vZGUpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcbiAgLyoqXHJcbiAgICogQHBhcmFtIHtCaW5hcnlUcmVlTm9kZX0gcm9vdE5vZGVcclxuICAgKi9cclxuICBwcml2YXRlIHJvdGF0ZUxlZnRSaWdodChyb290Tm9kZTogQmluYXJ5VHJlZU5vZGU8SywgVj4pOiB2b2lkIHtcclxuICAgIC8vIERldGFjaCBsZWZ0IG5vZGUgZnJvbSByb290Tm9kZSBzaW5jZSBpdCBpcyBnb2luZyB0byBiZSByZXBsYWNlZC5cclxuICAgIGNvbnN0IGxlZnROb2RlID0gcm9vdE5vZGUubGVmdCBhcyBCaW5hcnlUcmVlTm9kZTxLLCBWPjtcclxuICAgIHJvb3ROb2RlLnNldExlZnQobnVsbCk7XHJcblxyXG4gICAgLy8gRGV0YWNoIHJpZ2h0IG5vZGUgZnJvbSBsZWZ0Tm9kZS5cclxuICAgIGNvbnN0IGxlZnRSaWdodE5vZGUgPSBsZWZ0Tm9kZS5yaWdodDtcclxuICAgIGxlZnROb2RlLnNldFJpZ2h0KG51bGwpO1xyXG5cclxuICAgIGlmIChsZWZ0UmlnaHROb2RlICYmIGxlZnRSaWdodE5vZGUubGVmdCkge1xyXG4gICAgICAvLyBQcmVzZXJ2ZSBsZWZ0UmlnaHROb2RlJ3MgbGVmdCBzdWJ0cmVlLlxyXG4gICAgICBsZWZ0Tm9kZS5zZXRSaWdodChsZWZ0UmlnaHROb2RlLmxlZnQpO1xyXG4gICAgICAvLyBBdHRhY2ggbGVmdE5vZGUgYXMgbGVmdCBub2RlIGZvciBsZWZ0UmlnaHQgbm9kZS5cclxuICAgICAgbGVmdFJpZ2h0Tm9kZS5zZXRMZWZ0KG51bGwpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEF0dGFjaCBsZWZ0UmlnaHROb2RlIHRvIHRoZSByb290Tm9kZS5cclxuICAgIHJvb3ROb2RlLnNldExlZnQobGVmdFJpZ2h0Tm9kZSk7XHJcblxyXG4gICAgLy8gRG8gbGVmdC1sZWZ0IHJvdGF0aW9uLlxyXG4gICAgdGhpcy5yb3RhdGVMZWZ0TGVmdChyb290Tm9kZSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBwYXJhbSB7QmluYXJ5VHJlZU5vZGV9IHJvb3ROb2RlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByb3RhdGVSaWdodExlZnQocm9vdE5vZGU6IEJpbmFyeVRyZWVOb2RlPEssIFY+KTogdm9pZCB7XHJcbiAgICAvLyBEZXRhY2ggcmlnaHQgbm9kZSBmcm9tIHJvb3ROb2RlIHNpbmNlIGl0IGlzIGdvaW5nIHRvIGJlIHJlcGxhY2VkLlxyXG4gICAgY29uc3QgcmlnaHROb2RlID0gcm9vdE5vZGUucmlnaHQgYXMgQmluYXJ5VHJlZU5vZGU8SywgVj47XHJcbiAgICByb290Tm9kZS5zZXRSaWdodChudWxsKTtcclxuXHJcbiAgICAvLyBEZXRhY2ggbGVmdCBub2RlIGZyb20gcmlnaHROb2RlLlxyXG4gICAgY29uc3QgcmlnaHRMZWZ0Tm9kZSA9IHJpZ2h0Tm9kZS5sZWZ0O1xyXG4gICAgcmlnaHROb2RlLnNldExlZnQobnVsbCk7XHJcblxyXG4gICAgaWYgKHJpZ2h0TGVmdE5vZGUpIHtcclxuICAgICAgaWYgKHJpZ2h0TGVmdE5vZGUucmlnaHQpIHtcclxuICAgICAgICByaWdodE5vZGUuc2V0TGVmdChyaWdodExlZnROb2RlLnJpZ2h0KTtcclxuICAgICAgICAvL3JpZ2h0TGVmdE5vZGUuc2V0UmlnaHQobnVsbCk7XHJcbiAgICB9XHJcbiAgICAgIC8vIEF0dGFjaCByaWdodE5vZGUgYXMgcmlnaHQgbm9kZSBmb3IgcmlnaHRMZWZ0IG5vZGUuXHJcbiAgICAgIHJpZ2h0TGVmdE5vZGUuc2V0UmlnaHQocmlnaHROb2RlKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBdHRhY2ggcmlnaHRMZWZ0Tm9kZSB0byB0aGUgcm9vdE5vZGUuXHJcbiAgICByb290Tm9kZS5zZXRSaWdodChyaWdodExlZnROb2RlKTtcclxuXHJcbiAgICAvLyBBdHRhY2ggcmlnaHROb2RlIGFzIHJpZ2h0IG5vZGUgZm9yIHJpZ2h0TGVmdCBub2RlLlxyXG4gICAgLy9yaWdodExlZnROb2RlIS5zZXRSaWdodChyaWdodE5vZGUpO1xyXG5cclxuICAgIC8vIERvIHJpZ2h0LXJpZ2h0IHJvdGF0aW9uLlxyXG4gICAgdGhpcy5yb3RhdGVSaWdodFJpZ2h0KHJvb3ROb2RlKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQHBhcmFtIHtCaW5hcnlUcmVlTm9kZX0gcm9vdE5vZGVcclxuICAgKi9cclxuICBwcml2YXRlIHJvdGF0ZVJpZ2h0UmlnaHQocm9vdE5vZGU6IEJpbmFyeVRyZWVOb2RlPEssIFY+KTogdm9pZCB7XHJcbiAgICAvLyBEZXRhY2ggcmlnaHQgbm9kZSBmcm9tIHJvb3Qgbm9kZS5cclxuICAgIGNvbnN0IHJpZ2h0Tm9kZSA9IHJvb3ROb2RlLnJpZ2h0IGFzIEJpbmFyeVRyZWVOb2RlPEssIFY+O1xyXG4gICAgcm9vdE5vZGUuc2V0UmlnaHQobnVsbCk7XHJcblxyXG4gICAgLy8gTWFrZSByaWdodCBub2RlIHRvIGJlIGEgY2hpbGQgb2Ygcm9vdE5vZGUncyBwYXJlbnQuXHJcbiAgICBpZiAocm9vdE5vZGUucGFyZW50KSB7XHJcbiAgICAgIHJvb3ROb2RlLnBhcmVudC5zZXRMZWZ0KHJpZ2h0Tm9kZSk7XHJcbiAgICB9IGVsc2UgaWYgKHJvb3ROb2RlID09PSB0aGlzLnJvb3QpIHtcclxuICAgICAgLy8gSWYgcm9vdCBub2RlIGlzIHJvb3QgdGhlbiBtYWtlIHJpZ2h0IG5vZGUgdG8gYmUgYSBuZXcgcm9vdC5cclxuICAgICAgdGhpcy5yb290ID0gcmlnaHROb2RlO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIElmIHJpZ2h0IG5vZGUgaGFzIGEgbGVmdCBjaGlsZCB0aGVuIGRldGFjaCBpdCBhbmRcclxuICAgIC8vIGF0dGFjaCBpdCBhcyBhIHJpZ2h0IGNoaWxkIGZvciByb290Tm9kZS5cclxuICAgIGNvbnN0IHJpZ2h0TGVmdE5vZGUgPSByaWdodE5vZGUubGVmdDtcclxuXHJcbiAgICAvLyBBdHRhY2ggcm9vdE5vZGUgdG8gdGhlIGxlZnQgb2YgcmlnaHROb2RlLlxyXG4gICAgcmlnaHROb2RlLnNldExlZnQocm9vdE5vZGUpO1xyXG5cclxuICAgIGlmIChyaWdodExlZnROb2RlKSB7XHJcbiAgICAgIHJvb3ROb2RlLnNldFJpZ2h0KHJpZ2h0TGVmdE5vZGUpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcbn1cclxuIl19