@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
JavaScript
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