-
Notifications
You must be signed in to change notification settings - Fork 0
/
decorator.go
139 lines (120 loc) · 2.8 KB
/
decorator.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package behaviortree
import "time"
type Decorator struct {
Child Node
}
// A node that turns failure into success
// Do you want one for your life?
// Be carefull what you ask for,
// Because it also turns success into failure
type InverterNode struct {
BasicNode
Decorator
}
func (n *InverterNode) Update(state interface{}, messages []interface{}) []interface{} {
status, messages := Tick(n.Child, state, messages)
switch status {
case Success:
n.Status = Failure
case Failure:
n.Status = Success
default:
n.Status = status
}
return messages
}
func NewInverterNode(child Node) *InverterNode {
n := new(InverterNode)
n.Child = child
return n
}
// Runs the child and always returns the same status
type WrapConstantNode struct {
BasicNode
Decorator
}
func (n *WrapConstantNode) Update(state interface{}, messages []interface{}) []interface{} {
_, messages = Tick(n.Child, state, messages)
return messages
}
func NewWrapConstantNode(status Status, child Node) *WrapConstantNode {
n := new(WrapConstantNode)
n.Child = child
n.Status = status
return n
}
// Runs the child until limit is reached
type RepeaterNode struct {
BasicNode
Decorator
Counter int
Limit int
}
func (n *RepeaterNode) Initiate() {
n.Counter = 0
}
func (n *RepeaterNode) Update(state interface{}, messages []interface{}) []interface{} {
status, messages := Tick(n.Child, state, messages)
if status != Running {
n.Counter++
}
if n.Limit < 1 || n.Counter < n.Limit {
n.Status = Running
} else {
n.Status = status
}
return messages
}
func NewRepeaterNode(limit int, child Node) *RepeaterNode {
n := new(RepeaterNode)
n.Child = child
n.Limit = limit
return n
}
// Repeat Until the given status
type RepeatUntilNode struct {
BasicNode
Decorator
Until Status
}
func (n *RepeatUntilNode) Update(state interface{}, messages []interface{}) []interface{} {
status, messages := Tick(n.Child, state, messages)
if status == n.Until {
n.Status = Success
} else {
n.Status = Running
}
return messages
}
func NewRepeatUntilNode(until Status, child Node) *RepeatUntilNode {
n := new(RepeatUntilNode)
n.Child = child
n.Until = until
return n
}
type TimeoutNode struct {
BasicNode
Decorator
Timeout time.Duration
tchan <-chan time.Time
Completion Status
}
func (n *TimeoutNode) Initiate() {
n.tchan = time.After(n.Timeout)
}
func (n *TimeoutNode) Update(state interface{}, messages []interface{}) []interface{} {
select {
case <-n.tchan:
n.Status = n.Completion
default:
n.Status, messages = Tick(n.Child, state, messages)
}
return messages
}
func NewTimeoutNode(timeout time.Duration, completion Status, child Node) *TimeoutNode {
n := new(TimeoutNode)
n.Child = child
n.Timeout = timeout
n.Completion = completion
return n
}