-
Notifications
You must be signed in to change notification settings - Fork 2
/
tree.go
98 lines (85 loc) · 2.14 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
97
98
package main
import "github.com/nsaje/dagger/dagger"
type RelationalOperator int
const (
LT RelationalOperator = iota
GT
LTE
GTE
)
type LogicalOperator int
const (
OR LogicalOperator = iota
AND
)
type Node interface {
eval(valueTable valueTable) (bool, map[dagger.StreamID][]float64)
getLeafNodes() []LeafNode
}
type LeafNode struct {
streamID dagger.StreamID
relationalOperator RelationalOperator
threshold float64
periods int
}
func (n LeafNode) getLeafNodes() []LeafNode {
return []LeafNode{n}
}
func (n LeafNode) eval(vt valueTable) (bool, map[dagger.StreamID][]float64) {
result := true
values := make(map[dagger.StreamID][]float64)
values[n.streamID] = make([]float64, n.periods)
lastNRecords := vt.getLastN(n.streamID, n.periods)
if len(lastNRecords) == 0 {
return false, values
}
for i, r := range lastNRecords {
value := r.Data.(float64)
values[n.streamID][i] = value
switch n.relationalOperator {
case LT:
result = result && value < n.threshold
case GT:
result = result && value > n.threshold
case LTE:
result = result && value <= n.threshold
case GTE:
result = result && value >= n.threshold
}
}
return result, values
}
type BinNode struct {
op LogicalOperator
left Node
right Node
}
func mergeValues(l map[dagger.StreamID][]float64, r map[dagger.StreamID][]float64) map[dagger.StreamID][]float64 {
values := l
for k, rightVal := range r {
leftVal := l[k]
// skip if key already exists and contains a longer slice (larger periods value)
if leftVal != nil && len(leftVal) > len(rightVal) {
continue
}
values[k] = rightVal
}
return values
}
func (n BinNode) eval(vt valueTable) (bool, map[dagger.StreamID][]float64) {
leftResult, leftValues := n.left.eval(vt)
rightResult, rightValues := n.right.eval(vt)
values := mergeValues(leftValues, rightValues)
var result bool
if n.op == OR {
result = leftResult || rightResult
} else if n.op == AND {
result = leftResult && rightResult
} else {
panic("unknown operator")
}
return result, values
}
func (n BinNode) getLeafNodes() []LeafNode {
return append(n.left.getLeafNodes(), n.right.getLeafNodes()...)
}