Skip to content

Commit 8015b2a

Browse files
committed
[feature] Add game events to state and event procession
1 parent 4a157aa commit 8015b2a

File tree

7 files changed

+114
-76
lines changed

7 files changed

+114
-76
lines changed

internal/app/controller/engine.go

Lines changed: 80 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func (e *Engine) ResetGame() {
3333
e.State.TeamState[TeamYellow].TimeoutTimeLeft = e.config.Normal.TimeoutDuration
3434
e.State.TeamState[TeamBlue].TimeoutsLeft = e.config.Normal.Timeouts
3535
e.State.TeamState[TeamYellow].TimeoutsLeft = e.config.Normal.Timeouts
36+
e.RefereeEvents = []RefereeEvent{}
3637
e.History = History{}
3738
}
3839

@@ -45,6 +46,18 @@ func (e *Engine) Tick(delta time.Duration) {
4546
}
4647
}
4748

49+
func (e *Engine) SendCommand(command RefCommand, forTeam Team) {
50+
e.State.Command = command
51+
e.State.CommandFor = forTeam
52+
e.LogCommand()
53+
}
54+
55+
func (e *Engine) SendGameEvent(gameEvent GameEventType, forTeam Team) {
56+
e.State.GameEvent = gameEvent
57+
e.State.GameEventFor = forTeam
58+
e.LogGameEvent()
59+
}
60+
4861
// UndoLastAction restores the last state from internal history
4962
func (e *Engine) UndoLastAction() {
5063
lastIndex := len(e.History) - 2
@@ -55,39 +68,41 @@ func (e *Engine) UndoLastAction() {
5568
}
5669

5770
func (e *Engine) Process(event Event) error {
58-
cmd, err := e.processEvent(event)
71+
err := e.processEvent(event)
5972
if err != nil {
6073
return err
6174
}
62-
if cmd != nil {
63-
e.LogCommand(cmd)
64-
}
75+
e.appendHistory()
76+
return nil
77+
}
78+
79+
func (e *Engine) appendHistory() {
6580
e.History = append(e.History, HistoryEntry{*e.State, e.RefereeEvents})
6681
if len(e.History) > maxHistorySize {
6782
e.History = e.History[1:]
6883
}
69-
return nil
7084
}
7185

72-
func (e *Engine) LogGameEvent(eventType GameEventType) {
86+
func (e *Engine) LogGameEvent() {
7387
gameEvent := RefereeEvent{
74-
Timestamp: e.TimeProvider(),
75-
StageTime: e.State.StageTimeElapsed,
76-
Type: RefereeEventGameEvent,
77-
GameEventType: &eventType,
88+
Timestamp: e.TimeProvider(),
89+
StageTime: e.State.StageTimeElapsed,
90+
Type: RefereeEventGameEvent,
91+
Name: string(e.State.GameEvent),
92+
Team: e.State.GameEventFor,
7893
}
7994
e.RefereeEvents = append(e.RefereeEvents, gameEvent)
8095
}
8196

82-
func (e *Engine) LogCommand(command *EventCommand) {
83-
gameEvent := RefereeEvent{
97+
func (e *Engine) LogCommand() {
98+
refereeEvent := RefereeEvent{
8499
Timestamp: e.TimeProvider(),
85100
StageTime: e.State.StageTimeElapsed,
86101
Type: RefereeEventCommand,
87-
Command: &command.Type,
88-
Team: command.ForTeam,
102+
Name: string(e.State.Command),
103+
Team: e.State.CommandFor,
89104
}
90-
e.RefereeEvents = append(e.RefereeEvents, gameEvent)
105+
e.RefereeEvents = append(e.RefereeEvents, refereeEvent)
91106
}
92107

93108
func (e *Engine) loadStages() {
@@ -116,12 +131,12 @@ func (e *Engine) updateTimes(delta time.Duration) {
116131
}
117132
}
118133

119-
if e.State.GameState() == GameStateTimeout && e.State.CommandFor != nil {
120-
e.State.TeamState[*e.State.CommandFor].TimeoutTimeLeft -= delta
134+
if e.State.GameState() == GameStateTimeout && e.State.CommandFor.Known() {
135+
e.State.TeamState[e.State.CommandFor].TimeoutTimeLeft -= delta
121136
}
122137
}
123138

124-
func (e *Engine) processEvent(event Event) (*EventCommand, error) {
139+
func (e *Engine) processEvent(event Event) error {
125140
if event.Command != nil {
126141
return e.processCommand(event.Command)
127142
} else if event.Modify != nil {
@@ -135,37 +150,35 @@ func (e *Engine) processEvent(event Event) (*EventCommand, error) {
135150
} else if event.GameEvent != nil {
136151
return e.processGameEvent(event.GameEvent)
137152
}
138-
return nil, errors.New("unknown event")
153+
return errors.New("unknown event")
139154
}
140155

141-
func (e *Engine) processCommand(c *EventCommand) (*EventCommand, error) {
156+
func (e *Engine) processCommand(c *EventCommand) error {
157+
158+
if c.Type == CommandTimeout {
159+
e.State.TeamState[*c.ForTeam].TimeoutsLeft--
160+
} else if c.Type == CommandNormalStart {
161+
e.updatePreStages()
162+
}
142163
switch c.Type {
143164
case CommandDirect, CommandIndirect, CommandKickoff, CommandPenalty, CommandTimeout, CommandBallPlacement:
144165
if c.ForTeam == nil {
145-
return nil, errors.Errorf("Team required for %v", c.Type)
166+
return errors.Errorf("Team required for %v", c.Type)
146167
}
168+
e.SendCommand(c.Type, *c.ForTeam)
147169
case CommandHalt, CommandStop, CommandForceStart, CommandNormalStart:
170+
e.SendCommand(c.Type, "")
148171
default:
149-
return nil, errors.Errorf("Unknown command: %v", c)
172+
return errors.Errorf("Unknown command: %v", c)
150173
}
151174

152-
if c.Type == CommandTimeout {
153-
e.State.TeamState[*c.ForTeam].TimeoutsLeft--
154-
e.State.CommandFor = c.ForTeam
155-
} else if c.Type == CommandNormalStart {
156-
e.updatePreStages()
157-
}
158-
159-
e.State.Command = c.Type
160-
e.State.CommandFor = c.ForTeam
161-
162175
log.Printf("Processed command %v", *c)
163-
return c, nil
176+
return nil
164177
}
165178

166-
func (e *Engine) processModify(m *EventModifyValue) (*EventCommand, error) {
179+
func (e *Engine) processModify(m *EventModifyValue) error {
167180
if m.ForTeam.Unknown() {
168-
return nil, errors.Errorf("Unknown team: %v", m.ForTeam)
181+
return errors.Errorf("Unknown team: %v", m.ForTeam)
169182
}
170183
teamState := e.State.TeamState[m.ForTeam]
171184
if m.Goals != nil {
@@ -192,7 +205,7 @@ func (e *Engine) processModify(m *EventModifyValue) (*EventCommand, error) {
192205
} else if m.YellowCardTime != nil {
193206
cardId := m.YellowCardTime.CardID
194207
if cardId < 0 || cardId >= len(teamState.YellowCardTimes) {
195-
return nil, errors.Errorf("Invalid card index: %v", cardId)
208+
return errors.Errorf("Invalid card index: %v", cardId)
196209
}
197210
if duration, err := strToDuration(m.YellowCardTime.Duration); err == nil {
198211
teamState.YellowCardTimes[cardId] = duration
@@ -201,43 +214,40 @@ func (e *Engine) processModify(m *EventModifyValue) (*EventCommand, error) {
201214
if duration, err := strToDuration(*m.TimeoutTimeLeft); err == nil {
202215
teamState.TimeoutTimeLeft = duration
203216
} else {
204-
return nil, err
217+
return err
205218
}
206219
} else {
207-
return nil, errors.Errorf("Unknown modify: %v", m)
220+
return errors.Errorf("Unknown modify: %v", m)
208221
}
209222
log.Printf("Processed modification %v", m)
210-
return nil, nil
223+
return nil
211224
}
212225

213-
func (e *Engine) processStage(s *EventStage) (*EventCommand, error) {
226+
func (e *Engine) processStage(s *EventStage) error {
214227
if e.State.GameState() != GameStateHalted && e.State.GameState() != GameStateStopped {
215-
return nil, errors.New("The game state must be halted or stopped to change the stage")
228+
return errors.New("The game state must be halted or stopped to change the stage")
216229
}
217230

218-
var cmd *EventCommand
219231
if s.StageOperation == StageNext {
220-
cmd = e.updateStage(e.State.Stage.Next())
232+
e.updateStage(e.State.Stage.Next())
221233
} else if s.StageOperation == StagePrevious {
222-
cmd = e.updateStage(e.State.Stage.Previous())
234+
e.updateStage(e.State.Stage.Previous())
223235
} else {
224-
return nil, errors.Errorf("Unknown stage operation: %v", s.StageOperation)
236+
return errors.Errorf("Unknown stage operation: %v", s.StageOperation)
225237
}
226238

227239
log.Printf("Processed stage %v", s.StageOperation)
228240

229-
return cmd, nil
241+
return nil
230242
}
231243

232-
func (e *Engine) updateStage(stage Stage) (cmd *EventCommand) {
244+
func (e *Engine) updateStage(stage Stage) {
233245

234246
e.State.StageTimeLeft = e.StageTimes[stage]
235247
e.State.StageTimeElapsed = 0
236248

237249
if !e.State.Stage.IsPreStage() {
238-
e.State.Command = CommandHalt
239-
e.State.CommandFor = nil
240-
cmd = &EventCommand{nil, CommandHalt}
250+
e.SendCommand(CommandHalt, "")
241251
}
242252

243253
if stage == StageFirstHalf {
@@ -269,22 +279,22 @@ func (e *Engine) updatePreStages() {
269279
}
270280
}
271281

272-
func (e *Engine) processCard(card *EventCard) (*EventCommand, error) {
282+
func (e *Engine) processCard(card *EventCard) error {
273283
if card.ForTeam != TeamYellow && card.ForTeam != TeamBlue {
274-
return nil, errors.Errorf("Unknown team: %v", card.ForTeam)
284+
return errors.Errorf("Unknown team: %v", card.ForTeam)
275285
}
276286
if card.Type != CardTypeYellow && card.Type != CardTypeRed {
277-
return nil, errors.Errorf("Unknown card type: %v", card.Type)
287+
return errors.Errorf("Unknown card type: %v", card.Type)
278288
}
279289
teamState := e.State.TeamState[card.ForTeam]
280290
if card.Operation == CardOperationAdd {
281-
return nil, addCard(card, teamState, e.config.YellowCardDuration)
291+
return addCard(card, teamState, e.config.YellowCardDuration)
282292
} else if card.Operation == CardOperationRevoke {
283-
return nil, revokeCard(card, teamState)
293+
return revokeCard(card, teamState)
284294
} else if card.Operation == CardOperationModify {
285-
return nil, modifyCard(card, teamState)
295+
return modifyCard(card, teamState)
286296
}
287-
return nil, errors.Errorf("Unknown operation: %v", card.Operation)
297+
return errors.Errorf("Unknown operation: %v", card.Operation)
288298
}
289299

290300
func modifyCard(card *EventCard, teamState *TeamInfo) error {
@@ -311,7 +321,7 @@ func addCard(card *EventCard, teamState *TeamInfo, duration time.Duration) error
311321
return nil
312322
}
313323

314-
func (e *Engine) processTrigger(t *EventTrigger) (*EventCommand, error) {
324+
func (e *Engine) processTrigger(t *EventTrigger) error {
315325
if t.Type == TriggerResetMatch {
316326
e.ResetGame()
317327
} else if t.Type == TriggerSwitchColor {
@@ -325,16 +335,24 @@ func (e *Engine) processTrigger(t *EventTrigger) (*EventCommand, error) {
325335
} else if t.Type == TriggerUndo {
326336
e.UndoLastAction()
327337
} else {
328-
return nil, errors.Errorf("Unknown trigger: %v", t.Type)
338+
return errors.Errorf("Unknown trigger: %v", t.Type)
329339
}
330340
log.Printf("Processed trigger %v", t.Type)
331-
return nil, nil
341+
return nil
332342
}
333343

334-
func (e *Engine) processGameEvent(t *EventGameEvent) (*EventCommand, error) {
344+
func (e *Engine) processGameEvent(t *EventGameEvent) error {
345+
346+
if t.BallLeftFieldTouchLine != nil {
347+
e.SendGameEvent(GameEventBallLeftFieldTouchLine, t.BallLeftFieldTouchLine.Team)
348+
} else if t.BallLeftFieldGoalLine != nil {
349+
e.SendGameEvent(GameEventBallLeftFieldGoalLine, t.BallLeftFieldGoalLine.Team)
350+
} else {
351+
return errors.Errorf("Unknown game event: %v", *t)
352+
}
335353

336354
log.Printf("Processed game event %v", t)
337-
return nil, nil
355+
return nil
338356
}
339357

340358
func revokeCard(card *EventCard, teamState *TeamInfo) error {

internal/app/controller/gameEvents.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,25 @@ import "time"
44

55
type GameEventType string
66

7+
const (
8+
GameEventUnknown GameEventType = "unknown"
9+
GameEventBallLeftFieldTouchLine GameEventType = "ballLeftFieldTouchLine"
10+
GameEventBallLeftFieldGoalLine GameEventType = "ballLeftFieldGoalLine"
11+
)
12+
713
type RefereeEventType string
814

915
const (
1016
RefereeEventCommand RefereeEventType = "command"
17+
RefereeEventStage RefereeEventType = "stage"
1118
RefereeEventGameEvent RefereeEventType = "gameEvent"
1219
)
1320

1421
type RefereeEvent struct {
15-
Timestamp time.Time `json:"timestamp"`
16-
StageTime time.Duration `json:"stageTime"`
17-
Type RefereeEventType `json:"type"`
18-
GameEventType *GameEventType `json:"gameEventType"`
19-
Command *RefCommand `json:"command"`
20-
Team *Team `json:"team"`
21-
Description *string `json:"description"`
22+
Timestamp time.Time `json:"timestamp"`
23+
StageTime time.Duration `json:"stageTime"`
24+
Type RefereeEventType `json:"type"`
25+
Name string `json:"name"`
26+
Team Team `json:"team"`
27+
Description string `json:"description"`
2228
}

internal/app/controller/publisher.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func updateCommand(r *refproto.Referee, newCommand refproto.Referee_Command) {
113113
*r.CommandTimestamp = uint64(time.Now().UnixNano() / 1000)
114114
}
115115

116-
func mapCommand(command RefCommand, team *Team) refproto.Referee_Command {
116+
func mapCommand(command RefCommand, team Team) refproto.Referee_Command {
117117
switch command {
118118
case CommandHalt:
119119
return refproto.Referee_HALT
@@ -139,8 +139,8 @@ func mapCommand(command RefCommand, team *Team) refproto.Referee_Command {
139139
return -1
140140
}
141141

142-
func commandByTeam(team *Team, blueCommand refproto.Referee_Command, yellowCommand refproto.Referee_Command) refproto.Referee_Command {
143-
if *team == TeamBlue {
142+
func commandByTeam(team Team, blueCommand refproto.Referee_Command, yellowCommand refproto.Referee_Command) refproto.Referee_Command {
143+
if team == TeamBlue {
144144
return blueCommand
145145
}
146146
return yellowCommand

internal/app/controller/state.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ func (t Team) Unknown() bool {
3232
return t != "Yellow" && t != "Blue"
3333
}
3434

35+
// Known returns true if the team is blue or yellow
36+
func (t Team) Known() bool {
37+
return !t.Unknown()
38+
}
39+
3540
// Stage represents the different stages of a game
3641
type Stage string
3742

@@ -191,7 +196,9 @@ type TeamInfo struct {
191196
type State struct {
192197
Stage Stage `json:"stage"`
193198
Command RefCommand `json:"command"`
194-
CommandFor *Team `json:"commandForTeam"`
199+
GameEvent GameEventType `json:"gameEvent"`
200+
GameEventFor Team `json:"gameEventForTeam"`
201+
CommandFor Team `json:"commandForTeam"`
195202
StageTimeElapsed time.Duration `json:"stageTimeElapsed"`
196203
StageTimeLeft time.Duration `json:"stageTimeLeft"`
197204
MatchTimeStart time.Time `json:"matchTimeStart"`
@@ -204,6 +211,7 @@ func NewState() (s *State) {
204211
s = new(State)
205212
s.Stage = StagePreGame
206213
s.Command = CommandHalt
214+
s.GameEvent = GameEventUnknown
207215

208216
s.StageTimeLeft = 0
209217
s.StageTimeElapsed = 0

src/components/GameState.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
</span>
2121
|
2222
<span v-b-tooltip.hover title="Current command">
23-
{{state.command}} <span v-if="state.commandForTeam != null">for {{state.commandForTeam}}</span>
23+
{{state.command}} <span v-if="state.commandForTeam !== ''">for {{state.commandForTeam}}</span>
24+
</span>
25+
|
26+
<span v-b-tooltip.hover title="Last game event">
27+
{{state.gameEvent}} <span v-if="state.gameEventForTeam !== ''">for {{state.gameEventForTeam}}</span>
2428
</span>
2529
</div>
2630
</template>

src/components/events/EventTable.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
sortable: true
5353
},
5454
{
55-
key: 'command',
55+
key: 'name',
5656
sortable: false
5757
},
5858
{

0 commit comments

Comments
 (0)