You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					107 lines
				
				2.2 KiB
			
		
		
			
		
	
	
					107 lines
				
				2.2 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | const archy = require('archy') | ||
|  | 
 | ||
|  | function TimeTree () { | ||
|  |   this.root = null | ||
|  |   this.tableId = new Map() | ||
|  |   this.tableLabel = new Map() | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.trackNode = function (node) { | ||
|  |   this.tableId.set(node.id, node) | ||
|  |   if (this.tableLabel.has(node.label)) { | ||
|  |     this.tableLabel.get(node.label).push(node) | ||
|  |   } else { | ||
|  |     this.tableLabel.set(node.label, [node]) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.untrackNode = function (node) { | ||
|  |   this.tableId.delete(node.id) | ||
|  | 
 | ||
|  |   const labelNode = this.tableLabel.get(node.label) | ||
|  |   if (labelNode.id) { | ||
|  |     this.tableLabel.delete(node.label) | ||
|  |     return | ||
|  |   } | ||
|  |   labelNode.pop() | ||
|  | 
 | ||
|  |   if (labelNode.length === 0) { | ||
|  |     this.tableLabel.delete(node.label) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.getParent = function (parent) { | ||
|  |   if (parent === null) { | ||
|  |     return this.root | ||
|  |   } | ||
|  | 
 | ||
|  |   const parentNode = this.tableLabel.get(parent) | ||
|  |   if (parentNode.id) { | ||
|  |     return parentNode | ||
|  |   } | ||
|  |   return parentNode[parentNode.length - 1] | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.getNode = function (nodeId) { | ||
|  |   return this.tableId.get(nodeId) | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.add = function (parent, child, start) { | ||
|  |   const isRoot = parent === null | ||
|  |   if (isRoot) { | ||
|  |     this.root = { | ||
|  |       id: 'root', | ||
|  |       label: child, | ||
|  |       start, | ||
|  |       nodes: [] | ||
|  |     } | ||
|  |     this.trackNode(this.root) | ||
|  |     return this.root.id | ||
|  |   } | ||
|  | 
 | ||
|  |   const parentNode = this.getParent(parent) | ||
|  |   const nodeId = `${child}-${Math.random()}` | ||
|  |   const childNode = { | ||
|  |     id: nodeId, | ||
|  |     parent, | ||
|  |     start, | ||
|  |     label: child, | ||
|  |     nodes: [] | ||
|  |   } | ||
|  |   parentNode.nodes.push(childNode) | ||
|  |   this.trackNode(childNode) | ||
|  |   return nodeId | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.start = function (parent, child, start) { | ||
|  |   return this.add(parent, child, start || Date.now()) | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.stop = function (nodeId, stop) { | ||
|  |   const node = this.getNode(nodeId) | ||
|  |   if (node) { | ||
|  |     node.stop = stop || Date.now() | ||
|  |     node.diff = (node.stop - node.start) || 0 | ||
|  |     this.untrackNode(node) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.toJSON = function () { | ||
|  |   return Object.assign({}, this.root) | ||
|  | } | ||
|  | 
 | ||
|  | TimeTree.prototype.prittyPrint = function () { | ||
|  |   const decorateText = (node) => { | ||
|  |     node.label = `${node.label} ${node.diff} ms` | ||
|  |     if (node.nodes.length > 0) { | ||
|  |       node.nodes = node.nodes.map(_ => decorateText(_)) | ||
|  |     } | ||
|  |     return node | ||
|  |   } | ||
|  |   const out = decorateText(this.toJSON()) | ||
|  |   return archy(out) | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = TimeTree |