func (n *Node) Get(id int64) *Node {
	for _, node := range n.All() {
		if node.ID == id {
			return node
		}
	}
	return nil
}
Get returns the first node matching the ID, or nil, if no match is found.
package multitree
import (
	"fmt"
	"time"
)
type Node struct {
	ID   int64
	Name string
	Alias string
	Created int64
	Completed *int64
	parents  []*Node
	children []*Node
}
func NewNode(name string) *Node {
	return &Node{Name: name}
}
func (n *Node) nextID() int64 {
	var max int64
	for _, node := range n.All() {
		if node.ID > max {
			max = node.ID
		}
	}
	return max + 1
}
func (n *Node) New(name string) *Node {
	return &Node{ID: n.nextID(), Name: name}
}
func (n *Node) IsCompleted() bool {
	return n.Completed != nil
}
func (n *Node) IsCompletedOnDate(date string, offset int) bool {
	t := n.TimeCompleted()
	if !t.IsZero() {
		start, err := time.Parse("2006-01-02", date)
		if err != nil {
			panic(err)
		}
		start = start.Local().Add(time.Duration(offset) * time.Hour)
		end := start.Add(24 * time.Hour)
		if t.Equal(start) || (t.After(start) && t.Before(end)) {
			return true
		}
	}
	return false
}
func (n *Node) IsInProgress() bool {
	if n.IsCompleted() {
		return false
	}
	for _, d := range n.Descendants() {
		if d.IsCompleted() {
			return true
		}
	}
	return false
}
func (n *Node) IsInactive() bool {
	return !n.IsCompleted() && !n.IsInProgress()
}
func (n *Node) IsRoot() bool {
	return len(n.parents) == 0
}
func (n *Node) IsDateNode() bool {
	if n.IsRoot() && ValidateDateNodeName(n.Name) == nil {
		return true
	}
	return false
}
func (n *Node) TimeCompleted() time.Time {
	var t time.Time
	if n.Completed != nil {
		t = time.Unix(*n.Completed, 0)
	}
	return t
}
func (n *Node) Children() []*Node {
	return n.children
}
func (n *Node) Parents() []*Node {
	return n.parents
}
func (n *Node) Ancestors() []*Node {
	var nodes []*Node
	n.TraverseAncestors(func(current *Node, _ func()) {
		nodes = append(nodes, current)
	})
	if len(nodes) > 0 {
		return nodes[1:]
	}
	return nodes
}
func (n *Node) Descendants() []*Node {
	var nodes []*Node
	n.TraverseDescendants(func(current *Node, _ func()) {
		nodes = append(nodes, current)
	})
	if len(nodes) > 0 {
		return nodes[1:]
	}
	return nodes
}
func (n *Node) All() []*Node {
	var nodes []*Node
	n.DepthFirstSearchUndirected(func(cur *Node, ss SearchState, _ func()) {
		if ss == SearchStateWhite {
			nodes = append(nodes, cur)
		}
	})
	SortNodesByID(nodes)
	return nodes
}
func (n *Node) Roots() []*Node {
	var roots []*Node
	n.TraverseAncestors(func(current *Node, _ func()) {
		if current.IsRoot() {
			roots = append(roots, current)
		}
	})
	SortNodesByID(roots)
	return roots
}
func (n *Node) RootsAll() []*Node {
	var roots []*Node
	for _, node := range n.All() {
		if node.IsRoot() {
			roots = append(roots, node)
		}
	}
	SortNodesByID(roots)
	return roots
}
func (n *Node) IsLeaf() bool {
	return len(n.children) == 0
}
func (n *Node) HasChildren() bool {
	return len(n.children) != 0
}
func (n *Node) HasParents() bool {
	return len(n.parents) != 0
}
func (n *Node) Leaves() []*Node {
	var leaves []*Node
	n.TraverseDescendants(func(current *Node, _ func()) {
		if current.IsLeaf() {
			leaves = append(leaves, current)
		}
	})
	SortNodesByID(leaves)
	return leaves
}
func (n *Node) LeavesAll() []*Node {
	var leaves []*Node
	for _, node := range n.All() {
		if node.IsLeaf() {
			leaves = append(leaves, node)
		}
	}
	SortNodesByID(leaves)
	return leaves
}
func (n *Node) Tree() *Node {
	root := n.DeepCopy()
	root.parents = nil
	root.TraverseDescendants(func(current *Node, _ func()) {
		for _, child := range current.children {
			child.parents = []*Node{current}
		}
	})
	return root
}
func (n *Node) Copy() *Node {
	return &Node{
		ID:        n.ID,
		Name:      n.Name,
		Alias:     n.Alias,
		Created:   n.Created,
		Completed: copyCompletion(n.Completed),
	}
}
func (n *Node) DeepCopy() *Node {
	nodes := n.All()
	nodesByID := make(map[int64]*Node)
	for _, src := range nodes {
		nodesByID[src.ID] = src.Copy()
	}
	for _, src := range nodes {
		nodesByID[src.ID].parents = make([]*Node, len(src.parents))
		for i, p := range src.parents {
			nodesByID[src.ID].parents[i] = nodesByID[p.ID]
		}
		nodesByID[src.ID].children = make([]*Node, len(src.children))
		for i, c := range src.children {
			nodesByID[src.ID].children[i] = nodesByID[c.ID]
		}
	}
	return nodesByID[n.ID]
}
func (n *Node) HasChild(node *Node) bool {
	return nodesInclude(n.children, node)
}
func (n *Node) HasParent(node *Node) bool {
	return nodesInclude(n.parents, node)
}
func (n *Node) hasBackEdge() (found bool) {
	roots := n.RootsAll()
	if len(roots) == 0 {
		roots = append(roots, n)
	}
	for _, r := range roots {
		r.DepthFirstSearch(func(cur *Node, ss SearchState, stop func()) {
			if ss == SearchStateGray {
				found = true
				stop()
			}
		})
		if found {
			break
		}
	}
	return found
}
func (n *Node) hasDiamond() (found bool) {
	roots := n.RootsAll()
	if len(roots) == 0 {
		panic("cyclic graph passed to Node.hasDiamond")
	}
	for _, r := range roots {
		r.DepthFirstSearch(func(cur *Node, ss SearchState, stop func()) {
			if ss == SearchStateBlack {
				found = true
				stop()
			}
		})
		if found {
			break
		}
	}
	return found
}