/
tree.go
96 lines (86 loc) · 2.64 KB
/
tree.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package data
import (
"fmt"
)
// treeMap is a map whose key is a data id and the value is the list of data id.
// This map is used to map the children data to their parents (the key is a
// parent data id and the value is the list of ID of its children)
type treeMap map[TaskID]TaskIDArray
// addChild adds a child in the list of children of the data of ID parentID
func (tree *treeMap) addChild(parentID TaskID, childID TaskID) error {
if parentID == childID {
return fmt.Errorf("ERR: a child can not be parent of itself (ID=%v)", childID)
}
_, exists := (*tree)[parentID]
if !exists {
(*tree)[parentID] = make(TaskIDArray, 0)
}
(*tree)[parentID] = append((*tree)[parentID], childID)
return nil
}
// initialize initializes the tree structure from the data array
func (tree *treeMap) initialize(tasks TaskArray) error {
for i := 0; i < len(tasks); i++ {
task := tasks[i]
err := tree.addChild(TaskID(task.ParentID), TaskID(task.UIndex))
if err != nil {
return err
}
}
return nil
}
// TreeString returns a tree representation of the dataArray
func TreeString(tasks TaskArray) string {
// Create the children tree
tree := make(treeMap, 0)
tree.initialize(tasks)
// The principle is to iterate on dataArray root elements (element with no
// parent) and then create a string reresentation of the children tree using
// a recurcive function nodeString
const groupsep = "\n" // group separator (a group is a task that has no parent and has children)
const tabindent = " "
const tabchild = " └─"
//const tabchild = " └" + core.PrettyArrowRight
const tabstart = ""
startIndent := func(size int) string {
s := ""
for i := 0; i < size; i++ {
s += " "
}
return s
}(len(tabstart))
// nodeString is the recursive function
var nodeString func(taskID TaskID, tab string) string
nodeString = func(taskID TaskID, tab string) string {
idx := tasks.indexFromUID(taskID)
s := fmt.Sprintf("%s%s\n", tab, tasks[idx].String())
_, exists := tree[taskID]
if !exists {
// This task has no child
return s
}
children := tree[taskID]
if len(children) == 0 {
return s
}
if tab == tabstart {
// It is a project task (task with no parent AND with children
// tasks), then (1) the tabulation of children is starting with a
// startIndent and (2) we add a groupsep to the main task.
tab = startIndent + tabchild
s = groupsep + s
} else {
tab = tabindent + tab
}
for i := 0; i < len(children); i++ {
s += nodeString(children[i], tab)
}
return s
}
stree := ""
noParentTaskIDs := tree[NoUID]
for k := 0; k < len(noParentTaskIDs); k++ {
stree += nodeString(noParentTaskIDs[k], tabstart)
}
return stree
}