const { Node, Link, Graph } = require("./graph"); class TreeNode extends Node { constructor(id){ super(id); this.depth = null; } } class Tree extends Graph { constructor(){ super(); this.root = null; this.levels = []; } /*addLink(link) { console.log("You cannot add Link because its deprecated ...Use Insert"); return; } addNode(node){ console.log("You cannot add Node because its deprecated ...Use Insert"); return; }*/ changeParent(node, parent) { let link = this.links[node.id].in.values().next().value; let oldparent = link.from; this.links[oldparent.id].out.delete(link); link.from = parent; this.links[parent.id].out.add(link); this.updateLevels(parent); } updateLevels(node) { let outSet = this.links[node.id].out; for(let link of outSet) { let child = this.getNode(link.to); if(child.depth !== node.depth + 1) { if(child.depth){ this.levels[child.depth].delete(child.id); } child.depth = node.depth + 1; if(!this.levels[child.depth]){ this.levels[child.depth] = new Set(); } this.levels[child.depth].add(child.id); this.updateLevels(child); } } } insert(node,parentNode){ if(this.nodes[node.id]){ throw new Error("Node already Exists") } if(parentNode === null || parentNode === undefined) { super.addNode(node); this.root = node; this.root.depth = 0; this.levels = [new Set([this.root.id])]; return; } if(!this.nodes[parentNode.id]){ throw new Error("Parent Node does not Exist....Insert First ") } //console.log(node, parentNode); let link = new Link(parentNode.id,node.id); super.addNode(node); super.addLink(link); this.updateLevels(parentNode); } print() { console.log("§§§§§§§ Tree Structure §§§§§§§§§§"); this.levels.forEach((level, index) => { console.log("Level ", index); level.forEach( id => console.log(` ${id} `)); }); console.log("§§§§§§§ Tree Structure End §§§§§§§§§§"); } remove(node,propagation = true){ propagation ? this.cleanup(node) : null; this.levels[node.depth].delete(node.id); if(this.levels[node.depth].size === 0) { this.levels.length = node.depth; } super.removeNode(node); } cleanup(parent) { let children = this.getChildren(parent); children.forEach(child => { this.remove(child); }); } getParent(node) { return [...this.links[node.id].in].map(link => link.from)[0]; } getChildren(node) { return [...this.links[node.id].out].map(link => this.getNode(link.to)); } getLevel(depth) { return this.levels[depth]; } replaceNode(oldNode,newNode){ if(!this.nodes[oldNode.id]){ throw new Error("The Node you are trying to replace doesnt exist in the current Tree") } newNode.depth = oldNode.depth let OldLinks = this.getLinks(oldNode.id); let OldFromNode; let OldToNodes = []; let OldDepth = oldNode.depth; let levels = this.levels; for(let m of OldLinks.in){ OldFromNode = m.from } for(let k of OldLinks.out){ OldToNodes.push(k.to) } this.remove(oldNode,false); //If the tree contains only the root this code will run if(this.levels.length === 0){ this.levels = [new Set([newNode.id])] super.addNode(newNode); this.root = newNode; return true;; } //THIS PROCESS this.levels[OldDepth].add(newNode.id); super.addNode(newNode); if(OldFromNode){ super.linkNodes(OldFromNode,newNode.id); } OldToNodes.map((node) => { super.linkNodes(newNode.id,node) }) if(oldNode === this.root){ console.log("never") this.root = newNode } } export() { let data = super.export(); let levels = this.levels.map(level => Array.from(level)); return { ...data, levels, rootId: this.root.id }; } import(data, nodeType = TreeNode, parentNode) { let { levels, rootId, ...rest } = data; super.import(data, nodeType); if(!parentNode) { this.root = super.getNode(rootId); this.levels = levels.map(setArray => new Set(setArray)); } else { this.linkNodes(parentNode, rootId); this.updateLevels(this.getNode(parentNode)); } } } //console.log("SSSSSSSSSSSSSSSS") //console.log(A) //var B = new TreeNode('B'); //var C = new TreeNode('C'); //var D = new TreeNode('D'); //var E = new TreeNode('E'); //var F = new TreeNode("F"); //console.log(tree.root) //console.log(tree) // tree.insert(B,A) // tree.insert(D,B) // tree.insert(E,D) // tree.insert(F,D) // tree.print(); // tree.remove(D) // tree.print(); module.exports = { Tree, TreeNode };