1
1
package controller
2
2
3
3
import (
4
- "encoding/json"
5
4
"github.com/RoboCup-SSL/ssl-game-controller/pkg/timer"
6
- "io"
7
5
"log"
8
- "os"
9
- "time"
10
6
)
11
7
12
- const logDir = "logs"
13
- const lastStateFileName = logDir + "/lastState.json"
14
8
const configFileName = "config/ssl-game-controller.yaml"
15
9
16
10
// GameController controls a game
17
11
type GameController struct {
18
12
Config Config
19
- stateHistoryFile * os.File
20
- lastStateFile * os.File
21
13
Publisher Publisher
22
14
ApiServer ApiServer
23
15
Engine Engine
24
16
timer timer.Timer
17
+ historyPreserver HistoryPreserver
25
18
}
26
19
27
20
// NewGameController creates a new RefBox
@@ -42,34 +35,41 @@ func NewGameController() (r *GameController) {
42
35
// Run the GameController by starting an endless loop in the background
43
36
func (r * GameController ) Run () (err error ) {
44
37
45
- r .openStateFiles ()
46
- r .readLastState ()
38
+ if err := r .historyPreserver .Open (); err != nil {
39
+ log .Print ("Could not open history" , err )
40
+ } else {
41
+ history , err := r .historyPreserver .Load ()
42
+ if err != nil {
43
+ log .Print ("Could not load history" , err )
44
+ } else if len (* history ) > 0 {
45
+ r .Engine .History = * history
46
+ * r .Engine .State = r .Engine .History [len (r .Engine .History )- 1 ].State
47
+ r .Engine .RefereeEvents = r .Engine .History [len (r .Engine .History )- 1 ].RefereeEvents
48
+ }
49
+ }
50
+
51
+ r .ApiServer .PublishState (* r .Engine .State )
52
+ r .ApiServer .PublishGameEvents (r .Engine .RefereeEvents )
47
53
48
54
go func () {
49
- if r .stateHistoryFile != nil {
50
- defer r .stateHistoryFile .Close ()
51
- }
52
- if r .lastStateFile != nil {
53
- defer r .lastStateFile .Close ()
54
- }
55
+ defer r .historyPreserver .Close ()
55
56
for {
56
57
r .timer .WaitTillNextFullSecond ()
57
58
r .Engine .Tick (r .timer .Delta ())
58
- r .saveLatestState ( )
59
- r .publish (nil )
59
+ r .historyPreserver . Save ( r . Engine . History )
60
+ r .publish ()
60
61
}
61
62
}()
62
63
return nil
63
64
}
64
65
65
66
func (r * GameController ) OnNewEvent (event Event ) {
66
- cmd , err := r .Engine .Process (event )
67
+ err := r .Engine .Process (event )
67
68
if err != nil {
68
69
log .Println ("Could not process event:" , event , err )
69
70
} else {
70
- r .saveLatestState ()
71
- r .saveStateHistory ()
72
- r .publish (cmd )
71
+ r .historyPreserver .Save (r .Engine .History )
72
+ r .publish ()
73
73
r .publishGameEvents ()
74
74
}
75
75
}
@@ -90,81 +90,13 @@ func loadConfig() Config {
90
90
return config
91
91
}
92
92
93
- func (r * GameController ) openStateFiles () {
94
- os .MkdirAll (logDir , os .ModePerm )
95
-
96
- stateHistoryLogFileName := logDir + "/state-history_" + time .Now ().Format ("2006-01-02_15-04-05" ) + ".log"
97
- f , err := os .OpenFile (stateHistoryLogFileName , os .O_APPEND | os .O_WRONLY | os .O_CREATE , 0600 )
98
- if err != nil {
99
- log .Fatal ("Can not open state history log file" , err )
100
- }
101
- r .stateHistoryFile = f
102
-
103
- f , err = os .OpenFile (lastStateFileName , os .O_RDWR | os .O_CREATE , 0600 )
104
- if err != nil {
105
- log .Fatal ("Can not open last state file" , err )
106
- }
107
- r .lastStateFile = f
108
- }
109
-
110
- func (r * GameController ) readLastState () {
111
- bufSize := 10000
112
- b := make ([]byte , bufSize )
113
- n , err := r .lastStateFile .Read (b )
114
- if err != nil && err != io .EOF {
115
- log .Fatal ("Could not read from last state file " , err )
116
- }
117
- if n == bufSize {
118
- log .Fatal ("Buffer size too small" )
119
- }
120
- if n > 0 {
121
- err = json .Unmarshal (b [:n ], r .Engine .State )
122
- if err != nil {
123
- log .Fatalf ("Could not read last state: %v %v" , string (b ), err )
124
- }
125
- }
126
- }
127
-
128
93
// publish publishes the state to the UI and the teams
129
- func (r * GameController ) publish (command * EventCommand ) {
94
+ func (r * GameController ) publish () {
130
95
r .ApiServer .PublishState (* r .Engine .State )
131
96
r .Publisher .Publish (r .Engine .State )
132
97
}
133
98
134
99
// publishGameEvents publishes the current list of game events
135
100
func (r * GameController ) publishGameEvents () {
136
- r .ApiServer .PublishGameEvents (r .Engine .RefereeEvent )
137
- }
138
-
139
- // saveLatestState writes the current state into a file
140
- func (r * GameController ) saveLatestState () {
141
- jsonState , err := json .MarshalIndent (r .Engine .State , "" , " " )
142
- if err != nil {
143
- log .Print ("Can not marshal state " , err )
144
- return
145
- }
146
-
147
- err = r .lastStateFile .Truncate (0 )
148
- if err != nil {
149
- log .Fatal ("Can not truncate last state file " , err )
150
- }
151
- _ , err = r .lastStateFile .WriteAt (jsonState , 0 )
152
- if err != nil {
153
- log .Print ("Could not write last state " , err )
154
- }
155
- r .lastStateFile .Sync ()
156
- }
157
-
158
- // saveStateHistory writes the current state to the history file
159
- func (r * GameController ) saveStateHistory () {
160
-
161
- jsonState , err := json .Marshal (r .Engine .State )
162
- if err != nil {
163
- log .Print ("Can not marshal state " , err )
164
- return
165
- }
166
-
167
- r .stateHistoryFile .Write (jsonState )
168
- r .stateHistoryFile .WriteString ("\n " )
169
- r .stateHistoryFile .Sync ()
101
+ r .ApiServer .PublishGameEvents (r .Engine .RefereeEvents )
170
102
}
0 commit comments