{"dependencies":[{"name":"C:\\Users\\alexbol\\WebstormProjects\\flatten-js\\package.json","includedInParent":true,"mtime":1520238055570},{"name":"C:\\Users\\alexbol\\WebstormProjects\\flatten-js\\node_modules\\flatten-interval-tree\\package.json","includedInParent":true,"mtime":1520238156082},{"name":"./classes/node","loc":{"line":6,"column":19}},{"name":"./utils/constants","loc":{"line":7,"column":55}}],"generated":{"js":"/**\r\n * Created by Alex Bol on 3/31/2017.\r\n */\r\n'use strict';\r\n\r\nlet Node = require('./classes/node');\r\nlet {RB_TREE_COLOR_RED, RB_TREE_COLOR_BLACK} = require('./utils/constants');\r\n\r\nlet nil_node = new Node();\r\n\r\n/**\r\n * Implementation of interval binary search tree <br/>\r\n * Interval tree may store items which are couples of {key:interval, value: value} <br/>\r\n * Interval is an object with high and low properties or simply array of numeric [low,high] values <br />\r\n * If interval is an object, it should implement and expose methods less_than, equals_to, intersect and others,\r\n * see documentation {link}\r\n * @type {IntervalTree}\r\n */\r\nlet IntervalTree = class IntervalTree {\r\n    /**\r\n     * Construct new empty instance of IntervalTree\r\n     */\r\n    constructor() {\r\n        this.root = null;\r\n    }\r\n\r\n    /**\r\n     * Returns number of items stored in the interval tree\r\n     * @returns {number}\r\n     */\r\n    get size() {\r\n        let count = 0;\r\n        this.tree_walk(this.root, () => count++);\r\n        return count;\r\n    }\r\n\r\n    get keys() {\r\n        let res = [];\r\n        this.tree_walk(this.root, (node) => res.push(node.item.key.output()));\r\n        return res;\r\n    }\r\n\r\n    get isEmpty() {\r\n        return (this.root == null || this.root == nil_node);\r\n    }\r\n\r\n    /**\r\n     * Insert new item into interval tree\r\n     * @param key - interval object or array of two numbers [low, high]\r\n     * @param value - value representing any object (optional)\r\n     * @returns {Node} - returns reference to inserted node as an object {key:interval, value: value}\r\n     */\r\n    insert(key, value = key) {\r\n        if (key === undefined) return;\r\n        let insert_node = new Node(key, value, nil_node, nil_node, null, RB_TREE_COLOR_RED);\r\n        this.tree_insert(insert_node);\r\n        this.recalc_max(insert_node);\r\n        return insert_node;\r\n    }\r\n\r\n    /**\r\n     * Returns true if item {key,value} exist in the tree\r\n     * @param key - interval correspondent to keys stored in the tree\r\n     * @param value - value object to be checked\r\n     * @returns {boolean} - true if item {key, value} exist in the tree, false otherwise\r\n     */\r\n    exist(key, value) {\r\n        let search_node = new Node(key, value);\r\n        return this.tree_search(this.root, search_node) ? true : false;\r\n    }\r\n\r\n    /**\r\n     * Remove entry {key, value} from the tree\r\n     * @param key - interval correspondent to keys stored in the tree\r\n     * @param value - - value object\r\n     * @returns {boolean} - true if item {key, value} deleted, false if not found\r\n     */\r\n    remove(key, value) {\r\n        let search_node = new Node(key, value);\r\n        let delete_node = this.tree_search(this.root, search_node);\r\n        if (delete_node) {\r\n            this.tree_delete(delete_node);\r\n        }\r\n        return delete_node;\r\n    }\r\n\r\n    /**\r\n     * Returns array of entry values which keys intersect with given interval <br/>\r\n     * If no values stored in the tree, returns array of keys which intersect given interval\r\n     * @param interval - search interval, or array [low, high]\r\n     * @returns {Array}\r\n     */\r\n    search(interval) {\r\n        let search_node = new Node(interval);\r\n        let resp_nodes = [];\r\n        this.tree_search_interval(this.root, search_node, resp_nodes);\r\n        let resp = [];\r\n        resp_nodes.forEach((node) => {\r\n            if (node.item.value) {         // if there are values, return only values\r\n                resp.push(node.item.value);\r\n            }\r\n            else {                         // otherwise, return keys\r\n                resp.push(node.item.key.output());\r\n            }\r\n        }, []);\r\n        return resp;\r\n    }\r\n\r\n    /**\r\n     * Tree visitor. For each node implement a callback function. <br/>\r\n     * Method calls a callback function with two parameters (key, value)\r\n     * @param visitor(key,value) - function to be called for each tree item\r\n     */\r\n    forEach(visitor) {\r\n        this.tree_walk(this.root, (node) => visitor(node.item.key, node.item.value));\r\n    };\r\n\r\n    recalc_max(node) {\r\n        let node_current = node;\r\n        while (node_current.parent != null) {\r\n            node_current.parent.update_max();\r\n            node_current = node_current.parent;\r\n        }\r\n    }\r\n\r\n    tree_insert(insert_node) {\r\n        let current_node = this.root;\r\n        let parent_node = null;\r\n\r\n        if (this.root == null || this.root == nil_node) {\r\n            this.root = insert_node;\r\n        }\r\n        else {\r\n            while (current_node != nil_node) {\r\n                parent_node = current_node;\r\n                if (insert_node.less_than(current_node)) {\r\n                    current_node = current_node.left;\r\n                }\r\n                else {\r\n                    current_node = current_node.right;\r\n                }\r\n            }\r\n\r\n            insert_node.parent = parent_node;\r\n\r\n            if (insert_node.less_than(parent_node)) {\r\n                parent_node.left = insert_node;\r\n            }\r\n            else {\r\n                parent_node.right = insert_node;\r\n            }\r\n        }\r\n\r\n        this.insert_fixup(insert_node);\r\n    }\r\n\r\n// After insertion insert_node may have red-colored parent, and this is a single possible violation\r\n// Go upwords to the root and re-color until violation will be resolved\r\n    insert_fixup(insert_node) {\r\n        let current_node;\r\n        let uncle_node;\r\n\r\n        current_node = insert_node;\r\n        while (current_node != this.root && current_node.parent.color == RB_TREE_COLOR_RED) {\r\n            if (current_node.parent == current_node.parent.parent.left) {   // parent is left child of grandfather\r\n                uncle_node = current_node.parent.parent.right;              // right brother of parent\r\n                if (uncle_node.color == RB_TREE_COLOR_RED) {             // Case 1. Uncle is red\r\n                    // re-color father and uncle into black\r\n                    current_node.parent.color = RB_TREE_COLOR_BLACK;\r\n                    uncle_node.color = RB_TREE_COLOR_BLACK;\r\n                    current_node.parent.parent.color = RB_TREE_COLOR_RED;\r\n                    current_node = current_node.parent.parent;\r\n                }\r\n                else {                                                    // Case 2 & 3. Uncle is black\r\n                    if (current_node == current_node.parent.right) {     // Case 2. Current if right child\r\n                        // This case is transformed into Case 3.\r\n                        current_node = current_node.parent;\r\n                        this.rotate_left(current_node);\r\n                    }\r\n                    current_node.parent.color = RB_TREE_COLOR_BLACK;    // Case 3. Current is left child.\r\n                    // Re-color father and grandfather, rotate grandfather right\r\n                    current_node.parent.parent.color = RB_TREE_COLOR_RED;\r\n                    this.rotate_right(current_node.parent.parent);\r\n                }\r\n            }\r\n            else {                                                         // parent is right child of grandfather\r\n                uncle_node = current_node.parent.parent.left;              // left brother of parent\r\n                if (uncle_node.color == RB_TREE_COLOR_RED) {             // Case 4. Uncle is red\r\n                    // re-color father and uncle into black\r\n                    current_node.parent.color = RB_TREE_COLOR_BLACK;\r\n                    uncle_node.color = RB_TREE_COLOR_BLACK;\r\n                    current_node.parent.parent.color = RB_TREE_COLOR_RED;\r\n                    current_node = current_node.parent.parent;\r\n                }\r\n                else {\r\n                    if (current_node == current_node.parent.left) {             // Case 5. Current is left child\r\n                        // Transform into case 6\r\n                        current_node = current_node.parent;\r\n                        this.rotate_right(current_node);\r\n                    }\r\n                    current_node.parent.color = RB_TREE_COLOR_BLACK;    // Case 6. Current is right child.\r\n                    // Re-color father and grandfather, rotate grandfather left\r\n                    current_node.parent.parent.color = RB_TREE_COLOR_RED;\r\n                    this.rotate_left(current_node.parent.parent);\r\n                }\r\n            }\r\n        }\r\n\r\n        this.root.color = RB_TREE_COLOR_BLACK;\r\n    }\r\n\r\n    tree_delete(delete_node) {\r\n        let cut_node;   // node to be cut - either delete_node or successor_node  (\"y\" from 14.4)\r\n        let fix_node;   // node to fix rb tree property   (\"x\" from 14.4)\r\n\r\n        if (delete_node.left == nil_node || delete_node.right == nil_node) {  // delete_node has less then 2 children\r\n            cut_node = delete_node;\r\n        }\r\n        else {                                                    // delete_node has 2 children\r\n            cut_node = this.tree_successor(delete_node);\r\n        }\r\n\r\n        // fix_node if single child of cut_node\r\n        if (cut_node.left != nil_node) {\r\n            fix_node = cut_node.left;\r\n        }\r\n        else {\r\n            fix_node = cut_node.right;\r\n        }\r\n\r\n        // remove cut_node from parent\r\n        if (fix_node != nil_node) {\r\n            fix_node.parent = cut_node.parent;\r\n        }\r\n\r\n        if (cut_node == this.root) {\r\n            this.root = fix_node;\r\n        }\r\n        else {\r\n            if (cut_node == cut_node.parent.left) {\r\n                cut_node.parent.left = fix_node;\r\n            }\r\n            else {\r\n                cut_node.parent.right = fix_node;\r\n            }\r\n            cut_node.parent.update_max();        // update max property of the parent\r\n        }\r\n\r\n        this.recalc_max(fix_node);              // update max property upward from fix_node to root\r\n\r\n        // COPY DATA !!!\r\n        // Delete_node becomes cut_node, it means that we cannot hold reference\r\n        // to node in outer structure and we will have to delete by key, additional search need\r\n        if (cut_node != delete_node) {\r\n            delete_node.copy_data(cut_node);\r\n            delete_node.update_max();           // update max property of the cut node at the new place\r\n            this.recalc_max(delete_node);       // update max property upward from delete_node to root\r\n        }\r\n\r\n        if (fix_node != nil_node && cut_node.color == RB_TREE_COLOR_BLACK) {\r\n            this.delete_fixup(fix_node);\r\n        }\r\n    }\r\n\r\n    delete_fixup(fix_node) {\r\n        let current_node = fix_node;\r\n        let brother_node;\r\n\r\n        while (current_node != this.root && current_node.parent != null && current_node.color == RB_TREE_COLOR_BLACK) {\r\n            if (current_node == current_node.parent.left) {          // fix node is left child\r\n                brother_node = current_node.parent.right;\r\n                if (brother_node.color == RB_TREE_COLOR_RED) {   // Case 1. Brother is red\r\n                    brother_node.color = RB_TREE_COLOR_BLACK;         // re-color brother\r\n                    current_node.parent.color = RB_TREE_COLOR_RED;    // re-color father\r\n                    this.rotate_left(current_node.parent);\r\n                    brother_node = current_node.parent.right;                      // update brother\r\n                }\r\n                // Derive to cases 2..4: brother is black\r\n                if (brother_node.left.color == RB_TREE_COLOR_BLACK &&\r\n                    brother_node.right.color == RB_TREE_COLOR_BLACK) {  // case 2: both nephews black\r\n                    brother_node.color = RB_TREE_COLOR_RED;              // re-color brother\r\n                    current_node = current_node.parent;                  // continue iteration\r\n                }\r\n                else {\r\n                    if (brother_node.right.color == RB_TREE_COLOR_BLACK) {   // case 3: left nephew red, right nephew black\r\n                        brother_node.color = RB_TREE_COLOR_RED;          // re-color brother\r\n                        brother_node.left.color = RB_TREE_COLOR_BLACK;   // re-color nephew\r\n                        this.rotate_right(brother_node);\r\n                        brother_node = current_node.parent.right;                     // update brother\r\n                        // Derive to case 4: left nephew black, right nephew red\r\n                    }\r\n                    // case 4: left nephew black, right nephew red\r\n                    brother_node.color = current_node.parent.color;\r\n                    current_node.parent.color = RB_TREE_COLOR_BLACK;\r\n                    brother_node.right.color = RB_TREE_COLOR_BLACK;\r\n                    this.rotate_left(current_node.parent);\r\n                    current_node = this.root;                         // exit from loop\r\n                }\r\n            }\r\n            else {                                             // fix node is right child\r\n                brother_node = current_node.parent.left;\r\n                if (brother_node.color == RB_TREE_COLOR_RED) {   // Case 1. Brother is red\r\n                    brother_node.color = RB_TREE_COLOR_BLACK;         // re-color brother\r\n                    current_node.parent.color = RB_TREE_COLOR_RED;    // re-color father\r\n                    this.rotate_right(current_node.parent);\r\n                    brother_node = current_node.parent.left;                        // update brother\r\n                }\r\n                // Go to cases 2..4\r\n                if (brother_node.left.color == RB_TREE_COLOR_BLACK &&\r\n                    brother_node.right.color == RB_TREE_COLOR_BLACK) {   // case 2\r\n                    brother_node.color = RB_TREE_COLOR_RED;             // re-color brother\r\n                    current_node = current_node.parent;                              // continue iteration\r\n                }\r\n                else {\r\n                    if (brother_node.left.color == RB_TREE_COLOR_BLACK) {  // case 3: right nephew red, left nephew black\r\n                        brother_node.color = RB_TREE_COLOR_RED;            // re-color brother\r\n                        brother_node.right.color = RB_TREE_COLOR_BLACK;    // re-color nephew\r\n                        this.rotate_left(brother_node);\r\n                        brother_node = current_node.parent.left;                        // update brother\r\n                        // Derive to case 4: right nephew black, left nephew red\r\n                    }\r\n                    // case 4: right nephew black, left nephew red\r\n                    brother_node.color = current_node.parent.color;\r\n                    current_node.parent.color = RB_TREE_COLOR_BLACK;\r\n                    brother_node.left.color = RB_TREE_COLOR_BLACK;\r\n                    this.rotate_right(current_node.parent);\r\n                    current_node = this.root;                               // force exit from loop\r\n                }\r\n            }\r\n        }\r\n\r\n        current_node.color = RB_TREE_COLOR_BLACK;\r\n    }\r\n\r\n    tree_search(node, search_node) {\r\n        if (node == null || node == nil_node)\r\n            return undefined;\r\n\r\n        if (search_node.equal_to(node)) {\r\n            return node;\r\n        }\r\n        if (search_node.less_than(node)) {\r\n            return this.tree_search(node.left, search_node);\r\n        }\r\n        else {\r\n            return this.tree_search(node.right, search_node);\r\n        }\r\n    }\r\n\r\n    // Original search_interval method; container res support push() insertion\r\n    // Search all intervals intersecting given one\r\n    tree_search_interval(node, search_node, res) {\r\n        if (node != null && node != nil_node) {\r\n            // if (node->left != nil_node && node->left->max >= low) {\r\n            if (node.left != nil_node && !node.not_intersect_left_subtree(search_node)) {\r\n                this.tree_search_interval(node.left, search_node, res);\r\n            }\r\n            // if (low <= node->high && node->low <= high) {\r\n            if (node.intersect(search_node)) {\r\n                res.push(node);\r\n            }\r\n            // if (node->right != nil_node && node->low <= high) {\r\n            if (node.right != nil_node && !node.not_intersect_right_subtree(search_node)) {\r\n                this.tree_search_interval(node.right, search_node, res);\r\n            }\r\n        }\r\n    }\r\n\r\n    local_minimum(node) {\r\n        let node_min = node;\r\n        while (node_min.left != null && node_min.left != nil_node) {\r\n            node_min = node_min.left;\r\n        }\r\n        return node_min;\r\n    }\r\n\r\n    // not in use\r\n    local_maximum(node) {\r\n        let node_max = node;\r\n        while (node_max.right != null && node_max.right != nil_node) {\r\n            node_max = node_max.right;\r\n        }\r\n        return node_max;\r\n    }\r\n\r\n    tree_successor(node) {\r\n        let node_successor;\r\n        let current_node;\r\n        let parent_node;\r\n\r\n        if (node.right != nil_node) {\r\n            node_successor = this.local_minimum(node.right);\r\n        }\r\n        else {\r\n            current_node = node;\r\n            parent_node = node.parent;\r\n            while (parent_node != null && parent_node.right == current_node) {\r\n                current_node = parent_node;\r\n                parent_node = parent_node.parent;\r\n            }\r\n            node_successor = parent_node;\r\n        }\r\n        return node_successor;\r\n    }\r\n\r\n    //           |            right-rotate(T,y)       |\r\n    //           y            ---------------.       x\r\n    //          / \\                                  / \\\r\n    //         x   c          left-rotate(T,x)      a   y\r\n    //        / \\             <---------------         / \\\r\n    //       a   b                                    b   c\r\n\r\n    rotate_left(x) {\r\n        let y = x.right;\r\n\r\n        x.right = y.left;           // b goes to x.right\r\n\r\n        if (y.left != nil_node) {\r\n            y.left.parent = x;     // x becomes parent of b\r\n        }\r\n        y.parent = x.parent;       // move parent\r\n\r\n        if (x == this.root) {\r\n            this.root = y;           // y becomes root\r\n        }\r\n        else {                        // y becomes child of x.parent\r\n            if (x == x.parent.left) {\r\n                x.parent.left = y;\r\n            }\r\n            else {\r\n                x.parent.right = y;\r\n            }\r\n        }\r\n        y.left = x;                 // x becomes left child of y\r\n        x.parent = y;               // and y becomes parent of x\r\n\r\n        if (x != null && x != nil_node) {\r\n            x.update_max();\r\n        }\r\n\r\n        y = x.parent;\r\n        if (y != null && y != nil_node) {\r\n            y.update_max();\r\n        }\r\n    }\r\n\r\n    rotate_right(y) {\r\n        let x = y.left;\r\n\r\n        y.left = x.right;           // b goes to y.left\r\n\r\n        if (x.right != nil_node) {\r\n            x.right.parent = y;        // y becomes parent of b\r\n        }\r\n        x.parent = y.parent;          // move parent\r\n\r\n        if (y == this.root) {        // x becomes root\r\n            this.root = x;\r\n        }\r\n        else {                        // y becomes child of x.parent\r\n            if (y == y.parent.left) {\r\n                y.parent.left = x;\r\n            }\r\n            else {\r\n                y.parent.right = x;\r\n            }\r\n        }\r\n        x.right = y;                 // y becomes right child of x\r\n        y.parent = x;               // and x becomes parent of y\r\n\r\n        if (y != null && y != nil_node) {\r\n            y.update_max();\r\n        }\r\n\r\n        x = y.parent;\r\n        if (x != null && x != nil_node) {\r\n            x.update_max();\r\n        }\r\n    }\r\n\r\n    tree_walk(node, action) {\r\n        if (node != null && node != nil_node) {\r\n            this.tree_walk(node.left, action);\r\n            // arr.push(node.toArray());\r\n            action(node);\r\n            this.tree_walk(node.right, action);\r\n        }\r\n    }\r\n\r\n    /* Return true if all red nodes have exactly two black child nodes */\r\n    testRedBlackProperty() {\r\n        let res = true;\r\n        this.tree_walk(this.root, function (node) {\r\n            if (node.color == RB_TREE_COLOR_RED) {\r\n                if (!(node.left.color == RB_TREE_COLOR_BLACK && node.right.color == RB_TREE_COLOR_BLACK)) {\r\n                    res = false;\r\n                }\r\n            }\r\n        });\r\n        return res;\r\n    }\r\n\r\n    /* Throw error if not every path from root to bottom has same black height */\r\n    testBlackHeightProperty(node) {\r\n        let height = 0;\r\n        let heightLeft = 0;\r\n        let heightRight = 0;\r\n        if (node.color == RB_TREE_COLOR_BLACK) {\r\n            height++;\r\n        }\r\n        if (node.left != nil_node) {\r\n            heightLeft = this.testBlackHeightProperty(node.left);\r\n        }\r\n        else {\r\n            heightLeft = 1;\r\n        }\r\n        if (node.right != nil_node) {\r\n            heightRight = this.testBlackHeightProperty(node.right);\r\n        }\r\n        else {\r\n            heightRight = 1;\r\n        }\r\n        if (heightLeft != heightRight) {\r\n            throw new Error('Red-black height property violated');\r\n        }\r\n        height += heightLeft;\r\n        return height;\r\n    };\r\n};\r\n\r\nmodule.exports = IntervalTree;\r\n"},"hash":"0f0a81c7e12a319ba12e3a269e99caef","cacheData":{"env":{}}}