-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathstatemachine_test.go
122 lines (105 loc) · 3.9 KB
/
statemachine_test.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
// This is an example of how to use the statemachine pkg, based on statemachine_test.py
// from http://www.ibm.com/developerworks/library/l-python-state/index.html
// To quote from the explanation on that page:
// "The cargo is just a number that keeps getting fed back into an iterative function.
// The next value of val is always simply do_math(), as long as val stays within a certain range.
// Once the function returns a value outside that range, either the value is passed to a
// different handler or the state machine exits after calling a do-nothing end-state handler.
// One thing the example illustrates is that an event is not necessarily an input event.
// It can also be a computational event (atypically).
// The state-handlers differ from one another only in using a different marker when outputting
// the events they handle. This function is relatively trivial, and does not require using a state machine.
// But it illustrates the concept well."
package statemachine_test
import (
"fmt"
"math"
"github.com/dpapathanasiou/go-statemachine"
"testing"
)
func do_math(i float64) float64 {
return math.Abs(math.Sin(i) * 31.0)
}
func ones_counter() statemachine.Handler {
return func(val interface{}) (nextState string, nextVal interface{}) {
nextState = ""
nextVal = val.(float64)
fmt.Printf("1s State:\t")
for {
switch {
case (nextVal.(float64) <= 0 || nextVal.(float64) >= 30):
nextState = "outofrange"
case (nextVal.(float64) >= 20 && nextVal.(float64) < 30):
nextState = "twenties"
case (nextVal.(float64) >= 10 && nextVal.(float64) < 20):
nextState = "tens"
default:
fmt.Printf(" @ %2.1f+", nextVal.(float64))
}
if len(nextState) > 0 {
break
}
nextVal = do_math(nextVal.(float64))
}
fmt.Printf(" >>\n")
return
}
}
func tens_counter() statemachine.Handler {
return func(val interface{}) (nextState string, nextVal interface{}) {
nextState = ""
nextVal = val.(float64)
fmt.Printf("10s State:\t")
for {
switch {
case (nextVal.(float64) <= 0 || nextVal.(float64) >= 30):
nextState = "outofrange"
case (nextVal.(float64) >= 20 && nextVal.(float64) < 30):
nextState = "twenties"
case (nextVal.(float64) >= 1 && nextVal.(float64) < 10):
nextState = "ones"
default:
fmt.Printf(" #%2.1f+", nextVal)
}
if len(nextState) > 0 {
break
}
nextVal = do_math(nextVal.(float64))
}
fmt.Printf(" >>\n")
return
}
}
func twenties_counter() statemachine.Handler {
return func(val interface{}) (nextState string, nextVal interface{}) {
nextState = ""
nextVal = val.(float64)
fmt.Printf("20s State:\t")
for {
switch {
case (nextVal.(float64) <= 0 || nextVal.(float64) >= 30):
nextState = "outofrange"
case (nextVal.(float64) >= 10 && nextVal.(float64) < 20):
nextState = "tens"
case (nextVal.(float64) >= 1 && nextVal.(float64) < 10):
nextState = "ones"
default:
fmt.Printf(" *%2.1f+", nextVal)
}
if len(nextState) > 0 {
break
}
nextVal = do_math(nextVal.(float64))
}
fmt.Printf(" >>\n")
return
}
}
func TestStateMachine(t *testing.T) {
m := statemachine.Machine{map[string]statemachine.Handler{}, "ones", map[string]bool{}}
m.AddState("ones", ones_counter())
m.AddState("tens", tens_counter())
m.AddState("twenties", twenties_counter())
m.AddEndState("outofrange")
m.Execute(1.0)
}