11package controller
22
33import (
4- "encoding/json"
54 "github.com/RoboCup-SSL/ssl-game-controller/pkg/timer"
6- "io"
75 "log"
8- "os"
9- "time"
106)
117
12- const logDir = "logs"
13- const lastStateFileName = logDir + "/lastState.json"
148const configFileName = "config/ssl-game-controller.yaml"
159
1610// GameController controls a game
1711type GameController struct {
1812 Config Config
19- stateHistoryFile * os.File
20- lastStateFile * os.File
2113 Publisher Publisher
2214 ApiServer ApiServer
2315 Engine Engine
2416 timer timer.Timer
17+ historyPreserver HistoryPreserver
2518}
2619
2720// NewGameController creates a new RefBox
@@ -42,34 +35,41 @@ func NewGameController() (r *GameController) {
4235// Run the GameController by starting an endless loop in the background
4336func (r * GameController ) Run () (err error ) {
4437
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 )
4753
4854 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 ()
5556 for {
5657 r .timer .WaitTillNextFullSecond ()
5758 r .Engine .Tick (r .timer .Delta ())
58- r .saveLatestState ( )
59- r .publish (nil )
59+ r .historyPreserver . Save ( r . Engine . History )
60+ r .publish ()
6061 }
6162 }()
6263 return nil
6364}
6465
6566func (r * GameController ) OnNewEvent (event Event ) {
66- cmd , err := r .Engine .Process (event )
67+ err := r .Engine .Process (event )
6768 if err != nil {
6869 log .Println ("Could not process event:" , event , err )
6970 } else {
70- r .saveLatestState ()
71- r .saveStateHistory ()
72- r .publish (cmd )
71+ r .historyPreserver .Save (r .Engine .History )
72+ r .publish ()
7373 r .publishGameEvents ()
7474 }
7575}
@@ -90,81 +90,13 @@ func loadConfig() Config {
9090 return config
9191}
9292
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-
12893// publish publishes the state to the UI and the teams
129- func (r * GameController ) publish (command * EventCommand ) {
94+ func (r * GameController ) publish () {
13095 r .ApiServer .PublishState (* r .Engine .State )
13196 r .Publisher .Publish (r .Engine .State )
13297}
13398
13499// publishGameEvents publishes the current list of game events
135100func (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 )
170102}
0 commit comments