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

200 lines 21.3 kB
import { Comparator } from "../../util/Comparator"; import { BinaryTreeNode } from "./BinaryTreeNode"; /** * In computer science, binary search trees (BST), sometimes called ordered or sorted binary trees, * are a particular type of container: data structures that store "items" (such as numbers, names etc.) * in memory. They allow fast lookup, addition and removal of items, and can be used to implement * either dynamic sets of items, or lookup tables that allow finding an item by its key * (e.g., finding the phone number of a person by name). */ export class BinarySearchTree { constructor(comparator) { this.root = null; this.keyComparator = comparator ?? Comparator.getInstance(); } clear() { this.forEach((value, key) => { this.remove(key); }); } count() { let nCount = 0; this.forEach(() => nCount++); return nCount; } height() { if (this.root) { return this.root.height; } return 0; } /** * Test the tree for empness * @returns _true_ if the tree doesn't have child nodes, else _false_ */ isEmpty() { return (this.root == null); } /** * Inserts a new element to the tree * @param {K} key * @param {*} value * @returns {BinaryTreeNode} */ add(key, value) { if (this.root) { return this.root.add(key, value); } this.root = new BinaryTreeNode(key, value, this.keyComparator); return this.root; } /** * @param {*} key * @return {boolean} */ contains(key) { if (this.root) return this.root.contains(key); return false; } /** * * @param key * @returns */ get(key) { if (this.root) { const node = this.root.findNode(key); if (node) { return node.value; } } return undefined; } /** * @param {K} key * @returns {Element|undefined} */ remove(key) { if (this.root) { const removedNode = this.root.remove(key); if (removedNode) { return removedNode.value; } } return undefined; } /** * @return {string} */ toString() { if (this.root) return this.root.toString(); return ""; } /** * Executes a `callBack` function for each entry in this dictionary * @param callBack Function to call on each tree item * @param thisArg An object to which the `this` keyword can refer in the `callBack` function. If `thisArg` is omitted, undefined is used as the `this` value */ forEach(callBack, thisArg) { if (this.root) { this.root.traverse().forEach(node => callBack(node.value, node.key, node), thisArg); } } /** * Gets an array of the children keys for the specified `key` * @param key * @returns */ childrenKeys(key) { let keys = []; const keyNode = this.root?.findNode(key); if (keyNode) { keyNode.traverse("PreOrder!").forEach(node => keys.push(node.key), this); } return keys.slice(1); } /** * Gets an array of the parent keys for the specified `key` * @param key * @returns */ parentKeys(key) { let keys = []; const keyNode = this.root?.findNode(key); if (keyNode) { /* let it = keyNode.traverseUpIterator(); let res: IteratorResult<BinaryTreeNode<K,V>>; res = it.next(); while (!res.done) { keys.push(res.value.key); res = it.next(); } */ for (let node of keyNode.traverseUpIterator()) { keys.push(node.key); } } return keys.reverse(); } /** Returns the first (lowest) key currently in this map */ firstKey() { if (this.root) { return this.root.findMin().key; } return undefined; } /** Returns the last (highest) key currently in this map */ lastKey() { if (this.root) { return this.root.findMax().key; } return undefined; } keySet() { let set = new Set(); this.forEach((value, key) => set.add(key)); return set; } keys() { if (this.root) { return this.root.traverse().map(node => node.key); } return []; } values() { if (this.root) { return this.root.traverse().map(node => node.value); } return []; } *[Symbol.iterator]() { if (this.root) { yield* this.root.traverseDownIterator(); } } print(parentNode = null, indent = 0) { parentNode = parentNode ?? this.root; if (parentNode) { let height; let output = parentNode.key + "\r\n"; if (parentNode.left) { height = parentNode.left.height; output += "LEFT\r\n"; for (let node of parentNode.left.traverseDownIterator("PreOrder!")) { output += "\t".repeat(height - node.height - 1 + node.parent.direction + node.direction) + node.key + (node.direction == 1 ? "R" : "L") + "\r\n"; } } if (parentNode.right) { height = parentNode.right.height; output += "RIGHT\r\n"; for (let node of parentNode.right.traverseDownIterator("PreOrder!")) { output += "\t".repeat(height - node.height - 1 + node.parent.direction + node.direction) + node.key + (node.direction == 1 ? "R" : "L") + "\r\n"; } } return output; } return ""; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmluYXJ5U2VhcmNoVHJlZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2N1dGUtY29yZS9zcmMvbGliL2NvbGxlY3Rpb25zL3RyZWUvQmluYXJ5U2VhcmNoVHJlZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFbkQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRWxEOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxnQkFBZ0I7SUFJM0IsWUFBWSxVQUEwQjtRQUg1QixTQUFJLEdBQWdDLElBQUksQ0FBQztRQUlqRCxJQUFJLENBQUMsYUFBYSxHQUFHLFVBQVUsSUFBSSxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDOUQsQ0FBQztJQUVELEtBQUs7UUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRCxLQUFLO1FBQ0gsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFFLEVBQUUsQ0FBQSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzNCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNO1FBQ0osSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztTQUN6QjtRQUNELE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVEOzs7T0FHRztJQUNILE9BQU87UUFDTCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBQ0Q7Ozs7O09BS0c7SUFD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QUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLEVBQUU7b0JBQ25FLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFFLENBQUMsR0FBRSxJQUFJLENBQUMsTUFBTyxDQUFDLFNBQVMsR0FBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUUsQ0FBQyxDQUFBLENBQUMsQ0FBQSxHQUFHLENBQUEsQ0FBQyxDQUFBLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQztpQkFDMUk7YUFDRjtZQUNELE9BQU8sTUFBTSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7Q0FFRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBhcmF0b3IgfSBmcm9tIFwiLi4vLi4vdXRpbC9Db21wYXJhdG9yXCI7XHJcbmltcG9ydCB7IEVsZW1lbnQgfSBmcm9tIFwiLi4vQ29sbGVjdGlvblwiO1xyXG5pbXBvcnQgeyBCaW5hcnlUcmVlTm9kZSB9IGZyb20gXCIuL0JpbmFyeVRyZWVOb2RlXCI7XHJcblxyXG4vKipcclxuICogSW4gY29tcHV0ZXIgc2NpZW5jZSwgYmluYXJ5IHNlYXJjaCB0cmVlcyAoQlNUKSwgc29tZXRpbWVzIGNhbGxlZCBvcmRlcmVkIG9yIHNvcnRlZCBiaW5hcnkgdHJlZXMsXHJcbiAqIGFyZSBhIHBhcnRpY3VsYXIgdHlwZSBvZiBjb250YWluZXI6IGRhdGEgc3RydWN0dXJlcyB0aGF0IHN0b3JlIFwiaXRlbXNcIiAoc3VjaCBhcyBudW1iZXJzLCBuYW1lcyBldGMuKVxyXG4gKiBpbiBtZW1vcnkuIFRoZXkgYWxsb3cgZmFzdCBsb29rdXAsIGFkZGl0aW9uIGFuZCByZW1vdmFsIG9mIGl0ZW1zLCBhbmQgY2FuIGJlIHVzZWQgdG8gaW1wbGVtZW50XHJcbiAqIGVpdGhlciBkeW5hbWljIHNldHMgb2YgaXRlbXMsIG9yIGxvb2t1cCB0YWJsZXMgdGhhdCBhbGxvdyBmaW5kaW5nIGFuIGl0ZW0gYnkgaXRzIGtleVxyXG4gKiAoZS5nLiwgZmluZGluZyB0aGUgcGhvbmUgbnVtYmVyIG9mIGEgcGVyc29uIGJ5IG5hbWUpLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEJpbmFyeVNlYXJjaFRyZWU8SywgVj1LPiB7XHJcbiAgcHJvdGVjdGVkIHJvb3Q6IEJpbmFyeVRyZWVOb2RlPEssIFY+IHwgbnVsbCA9IG51bGw7XHJcbiAgcmVhZG9ubHkga2V5Q29tcGFyYXRvcjogQ29tcGFyYXRvcjxLPjtcclxuXHJcbiAgY29uc3RydWN0b3IoY29tcGFyYXRvcj86IENvbXBhcmF0b3I8Sz4pIHtcclxuICAgIHRoaXMua2V5Q29tcGFyYXRvciA9IGNvbXBhcmF0b3IgPz8gQ29tcGFyYXRvci5nZXRJbnN0YW5jZSgpO1xyXG4gIH1cclxuXHJcbiAgY2xlYXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHsgdGhpcy5yZW1vdmUoa2V5KSB9KTtcclxuICB9XHJcblxyXG4gIGNvdW50KCk6IG51bWJlciB7XHJcbiAgICBsZXQgbkNvdW50ID0gMDtcclxuICAgIHRoaXMuZm9yRWFjaCgoKT0+bkNvdW50KyspO1xyXG4gICAgcmV0dXJuIG5Db3VudDtcclxuICB9XHJcblxyXG4gIGhlaWdodCgpOiBudW1iZXIge1xyXG4gICAgaWYgKHRoaXMucm9vdCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5yb290LmhlaWdodDtcclxuICAgIH1cclxuICAgIHJldHVybiAwO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGVzdCB0aGUgdHJlZSBmb3IgZW1wbmVzc1xyXG4gICAqIEByZXR1cm5zIF90cnVlXyBpZiB0aGUgdHJlZSBkb2Vzbid0IGhhdmUgY2hpbGQgbm9kZXMsIGVsc2UgX2ZhbHNlX1xyXG4gICAqL1xyXG4gIGlzRW1wdHkoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKHRoaXMucm9vdCA9PSBudWxsKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogSW5zZXJ0cyBhIG5ldyBlbGVtZW50IHRvIHRoZSB0cmVlXHJcbiAgICogQHBhcmFtIHtLfSBrZXlcclxuICAgKiBAcGFyYW0geyp9IHZhbHVlXHJcbiAgICogQHJldHVybnMge0JpbmFyeVRyZWVOb2RlfVxyXG4gICAqL1xyXG4gIGFkZChrZXk6IEssIHZhbHVlOiBFbGVtZW50PFY+KTogQmluYXJ5VHJlZU5vZGU8SywgVj4ge1xyXG4gICAgaWYgKHRoaXMucm9vdCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5yb290LmFkZChrZXksIHZhbHVlKTtcclxuICAgIH1cclxuICAgIHRoaXMucm9vdCA9IG5ldyBCaW5hcnlUcmVlTm9kZTxLLCBWPihrZXksIHZhbHVlLCB0aGlzLmtleUNvbXBhcmF0b3IpO1xyXG4gICAgcmV0dXJuIHRoaXMucm9vdDtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQHBhcmFtIHsqfSBrZXlcclxuICAgKiBAcmV0dXJuIHtib29sZWFufVxyXG4gICAqL1xyXG4gIGNvbnRhaW5zKGtleTogSyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMucm9vdClcclxuICAgICAgcmV0dXJuIHRoaXMucm9vdC5jb250YWlucyhrZXkpO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuICAvKipcclxuICAgKlxyXG4gICAqIEBwYXJhbSBrZXlcclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGdldChrZXk6IEspOiBFbGVtZW50PFY+IHwgdW5kZWZpbmVkIHtcclxuICAgIGlmICh0aGlzLnJvb3QpIHtcclxuICAgICAgY29uc3Qgbm9kZSA9IHRoaXMucm9vdC5maW5kTm9kZShrZXkpO1xyXG4gICAgICBpZiAobm9kZSkge1xyXG4gICAgICAgIHJldHVybiBub2RlLnZhbHVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAcGFyYW0ge0t9IGtleVxyXG4gICAqIEByZXR1cm5zIHtFbGVtZW50fHVuZGVmaW5lZH1cclxuICAgKi9cclxuICByZW1vdmUoa2V5OiBLKTogRWxlbWVudDxWPiB8IHVuZGVmaW5lZCB7XHJcbiAgICBpZiAodGhpcy5yb290KSB7XHJcbiAgICAgIGNvbnN0IHJlbW92ZWROb2RlID0gdGhpcy5yb290LnJlbW92ZShrZXkpO1xyXG4gICAgICBpZiAocmVtb3ZlZE5vZGUpIHtcclxuICAgICAgICByZXR1cm4gcmVtb3ZlZE5vZGUudmFsdWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgKi9cclxuICB0b1N0cmluZygpOiBzdHJpbmcge1xyXG4gICAgaWYgKHRoaXMucm9vdClcclxuICAgICAgcmV0dXJuIHRoaXMucm9vdC50b1N0cmluZygpO1xyXG4gICAgcmV0dXJuIFwiXCI7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEV4ZWN1dGVzIGEgYGNhbGxCYWNrYCBmdW5jdGlvbiBmb3IgZWFjaCBlbnRyeSBpbiB0aGlzIGRpY3Rpb25hcnlcclxuICAgKiBAcGFyYW0gY2FsbEJhY2sgIEZ1bmN0aW9uIHRvIGNhbGwgb24gZWFjaCB0cmVlIGl0ZW1cclxuICAgKiBAcGFyYW0gdGhpc0FyZyAgIEFuIG9iamVjdCB0byB3aGljaCB0aGUgYHRoaXNgIGtleXdvcmQgY2FuIHJlZmVyIGluIHRoZSBgY2FsbEJhY2tgIGZ1bmN0aW9uLiBJZiBgdGhpc0FyZ2AgaXMgb21pdHRlZCwgdW5kZWZpbmVkIGlzIHVzZWQgYXMgdGhlIGB0aGlzYCB2YWx1ZVxyXG4gICAqL1xyXG4gIGZvckVhY2goY2FsbEJhY2s6ICh2YWx1ZTogRWxlbWVudDxWPiwga2V5OiBLLCBub2RlOiBCaW5hcnlUcmVlTm9kZTxLLCBWPikgPT4gdm9pZCwgdGhpc0FyZz86IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMucm9vdCkge1xyXG4gICAgICB0aGlzLnJvb3QudHJhdmVyc2UoKS5mb3JFYWNoKG5vZGUgPT4gY2FsbEJhY2sobm9kZS52YWx1ZSwgbm9kZS5rZXksIG5vZGUpLCB0aGlzQXJnKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2V0cyBhbiBhcnJheSBvZiB0aGUgY2hpbGRyZW4ga2V5cyBmb3IgdGhlIHNwZWNpZmllZCBga2V5YFxyXG4gICAqIEBwYXJhbSBrZXlcclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGNoaWxkcmVuS2V5cyhrZXk6IEspOiBBcnJheTxLPiB7XHJcbiAgICBsZXQga2V5czogS1tdID0gW107XHJcbiAgICBjb25zdCBrZXlOb2RlID0gdGhpcy5yb290Py5maW5kTm9kZShrZXkpO1xyXG4gICAgaWYgKGtleU5vZGUpIHtcclxuICAgICAga2V5Tm9kZS50cmF2ZXJzZShcIlByZU9yZGVyIVwiKS5mb3JFYWNoKG5vZGUgPT4ga2V5cy5wdXNoKG5vZGUua2V5KSwgdGhpcyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4ga2V5cy5zbGljZSgxKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2V0cyBhbiBhcnJheSBvZiB0aGUgcGFyZW50IGtleXMgZm9yIHRoZSBzcGVjaWZpZWQgYGtleWBcclxuICAgKiBAcGFyYW0ga2V5XHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBwYXJlbnRLZXlzKGtleTogSyk6IEFycmF5PEs+IHtcclxuICAgIGxldCBrZXlzOiBLW10gPSBbXTtcclxuICAgIGNvbnN0IGtleU5vZGUgPSB0aGlzLnJvb3Q/LmZpbmROb2RlKGtleSk7XHJcbiAgICBpZiAoa2V5Tm9kZSkge1xyXG4gICAgICAvKlxyXG4gICAgICBsZXQgaXQgPSBrZXlOb2RlLnRyYXZlcnNlVXBJdGVyYXRvcigpO1xyXG4gICAgICBsZXQgcmVzOiBJdGVyYXRvclJlc3VsdDxCaW5hcnlUcmVlTm9kZTxLLFY+PjtcclxuICAgICAgcmVzID0gaXQubmV4dCgpO1xyXG4gICAgICB3aGlsZSAoIXJlcy5kb25lKSB7XHJcbiAgICAgICAga2V5cy5wdXNoKHJlcy52YWx1ZS5rZXkpO1xyXG4gICAgICAgIHJlcyA9IGl0Lm5leHQoKTtcclxuICAgICAgfVxyXG4gICAgICAqL1xyXG4gICAgICBmb3IgKGxldCBub2RlIG9mIGtleU5vZGUudHJhdmVyc2VVcEl0ZXJhdG9yKCkpIHtcclxuICAgICAgICBrZXlzLnB1c2gobm9kZS5rZXkpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4ga2V5cy5yZXZlcnNlKCk7XHJcbiAgfVxyXG4gIC8qKiBSZXR1cm5zIHRoZSBmaXJzdCAobG93ZXN0KSBrZXkgY3VycmVudGx5IGluIHRoaXMgbWFwICovXHJcbiAgZmlyc3RLZXkoKTogSyB8IHVuZGVmaW5lZCB7XHJcbiAgICBpZiAodGhpcy5yb290KSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnJvb3QuZmluZE1pbigpLmtleTtcclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgfVxyXG4gIC8qKiBSZXR1cm5zIHRoZSBsYXN0IChoaWdoZXN0KSBrZXkgY3VycmVudGx5IGluIHRoaXMgbWFwICovXHJcbiAgbGFzdEtleSgpOiBLIHwgdW5kZWZpbmVkIHtcclxuICAgIGlmICh0aGlzLnJvb3QpIHtcclxuICAgICAgcmV0dXJuIHRoaXMucm9vdC5maW5kTWF4KCkua2V5O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIGtleVNldCgpOiBTZXQ8Sz4ge1xyXG4gICAgbGV0IHNldCA9IG5ldyBTZXQ8Sz4oKTtcclxuICAgIHRoaXMuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4gc2V0LmFkZChrZXkpKTtcclxuICAgIHJldHVybiBzZXQ7XHJcbiAgfVxyXG5cclxuICBrZXlzKCk6IEFycmF5PEs+IHtcclxuICAgIGlmICh0aGlzLnJvb3QpIHtcclxuICAgICAgcmV0dXJuIHRoaXMucm9vdC50cmF2ZXJzZSgpLm1hcChub2RlID0+IG5vZGUua2V5KTtcclxuICAgIH1cclxuICAgIHJldHVybiBbXTtcclxuICB9XHJcblxyXG4gIHZhbHVlcygpOiBBcnJheTxFbGVtZW50PFY+PiB7XHJcbiAgICBpZiAodGhpcy5yb290KSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnJvb3QudHJhdmVyc2UoKS5tYXAobm9kZSA9PiBub2RlLnZhbHVlKTtcclxuICAgIH1cclxuICAgIHJldHVybiBbXTtcclxuICB9XHJcblxyXG4gICpbU3ltYm9sLml0ZXJhdG9yXSgpOiBJdGVyYWJsZUl0ZXJhdG9yPEJpbmFyeVRyZWVOb2RlPEssIFY+PiB7XHJcbiAgICBpZiAodGhpcy5yb290KSB7XHJcbiAgICAgIHlpZWxkKiB0aGlzLnJvb3QudHJhdmVyc2VEb3duSXRlcmF0b3IoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaW50KHBhcmVudE5vZGU6IEJpbmFyeVRyZWVOb2RlPEssIFY+IHwgbnVsbCA9IG51bGwsIGluZGVudDogbnVtYmVyID0gMCk6IHN0cmluZyB7XHJcbiAgICBwYXJlbnROb2RlID0gcGFyZW50Tm9kZSA/PyB0aGlzLnJvb3Q7XHJcbiAgICBpZiAocGFyZW50Tm9kZSkge1xyXG4gICAgICBsZXQgaGVpZ2h0XHJcbiAgICAgIGxldCBvdXRwdXQgPSBwYXJlbnROb2RlLmtleStcIlxcclxcblwiO1xyXG4gICAgICBpZiAocGFyZW50Tm9kZS5sZWZ0KSB7XHJcbiAgICAgICAgaGVpZ2h0ID0gcGFyZW50Tm9kZS5sZWZ0LmhlaWdodDtcclxuICAgICAgICBvdXRwdXQgKz0gXCJMRUZUXFxyXFxuXCI7XHJcbiAgICAgICAgZm9yIChsZXQgbm9kZSBvZiBwYXJlbnROb2RlLmxlZnQudHJhdmVyc2VEb3duSXRlcmF0b3IoXCJQcmVPcmRlciFcIikpIHtcclxuICAgICAgICAgIG91dHB1dCArPSBcIlxcdFwiLnJlcGVhdChoZWlnaHQgLSBub2RlLmhlaWdodCAtMSsgbm9kZS5wYXJlbnQhLmRpcmVjdGlvbiArIG5vZGUuZGlyZWN0aW9uKSArIG5vZGUua2V5ICsgKG5vZGUuZGlyZWN0aW9uPT0xP1wiUlwiOlwiTFwiKSArIFwiXFxyXFxuXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGlmIChwYXJlbnROb2RlLnJpZ2h0KSB7XHJcbiAgICAgICAgaGVpZ2h0ID0gcGFyZW50Tm9kZS5yaWdodC5oZWlnaHQ7XHJcbiAgICAgICAgb3V0cHV0ICs9IFwiUklHSFRcXHJcXG5cIjtcclxuICAgICAgICBmb3IgKGxldCBub2RlIG9mIHBhcmVudE5vZGUucmlnaHQudHJhdmVyc2VEb3duSXRlcmF0b3IoXCJQcmVPcmRlciFcIikpIHtcclxuICAgICAgICAgIG91dHB1dCArPSBcIlxcdFwiLnJlcGVhdChoZWlnaHQgLSBub2RlLmhlaWdodCAtMSsgbm9kZS5wYXJlbnQhLmRpcmVjdGlvbiArbm9kZS5kaXJlY3Rpb24pICsgbm9kZS5rZXkgKyAobm9kZS5kaXJlY3Rpb249PTE/XCJSXCI6XCJMXCIpICsgXCJcXHJcXG5cIjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG91dHB1dDtcclxuICAgIH1cclxuICAgIHJldHVybiBcIlwiO1xyXG4gIH1cclxuXHJcbn1cclxuIl19