Skip to content

Commit 153f1aa

Browse files
committed
[feature] Add "Place ball" button to UI and backend API
1 parent aee1fa0 commit 153f1aa

File tree

8 files changed

+99
-13
lines changed

8 files changed

+99
-13
lines changed

internal/app/controller/engine.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ func (e *Engine) processEvent(event Event) error {
280280
}
281281

282282
func (e *Engine) processCommand(c *EventCommand) error {
283+
e.State.PlacementPos = c.Location
283284
switch c.Type {
284285
case CommandDirect, CommandIndirect, CommandKickoff, CommandPenalty, CommandTimeout, CommandBallPlacement:
285286
if c.ForTeam == nil {

internal/app/controller/events.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,19 @@ type EventCard struct {
7575

7676
// EventCommand is an event that can be applied
7777
type EventCommand struct {
78-
ForTeam *Team `json:"forTeam"`
79-
Type RefCommand `json:"commandType"`
78+
ForTeam *Team `json:"forTeam"`
79+
Type RefCommand `json:"commandType"`
80+
Location *Location `json:"location"`
8081
}
8182

8283
func (c EventCommand) String() string {
8384
if c.ForTeam == nil {
8485
return string(c.Type)
8586
}
86-
return fmt.Sprintf("%v for %v", c.Type, *c.ForTeam)
87+
if c.Location == nil {
88+
return fmt.Sprintf("%v for %v", c.Type, *c.ForTeam)
89+
}
90+
return fmt.Sprintf("%v for %v at %v", c.Type, *c.ForTeam, *c.Location)
8791
}
8892

8993
// EventModifyCardTime holds the duration for a certain yellow card duration

internal/app/controller/publisher.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func mapLocation(location *Location) *refproto.Referee_Point {
269269
if location == nil {
270270
return nil
271271
}
272-
x := float32(location.X)
273-
y := float32(location.Y)
272+
x := float32(location.X) * 1000.0
273+
y := float32(location.Y) * 1000.0
274274
return &refproto.Referee_Point{X: &x, Y: &y}
275275
}

internal/app/controller/state.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controller
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/config"
67
"github.com/RoboCup-SSL/ssl-game-controller/pkg/refproto"
78
"github.com/pkg/errors"
@@ -449,8 +450,8 @@ func (s *State) TeamByName(teamName string) Team {
449450

450451
// Location is a two-dimensional coordinate
451452
type Location struct {
452-
X float64
453-
Y float64
453+
X float64 `json:"x"`
454+
Y float64 `json:"y"`
454455
}
455456

456457
func (l Location) toProto() (p *refproto.Location) {
@@ -461,3 +462,7 @@ func (l Location) toProto() (p *refproto.Location) {
461462
*p.Y = float32(l.Y)
462463
return
463464
}
465+
466+
func (l Location) String() string {
467+
return fmt.Sprintf("%.3fm | %.3fm", l.X, l.Y)
468+
}

internal/app/controller/uiProtocol.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,17 @@ func (e *Engine) LogIgnoredGameEvent(event GameEvent) {
6363

6464
// LogCommand adds a command to the protocol
6565
func (e *Engine) LogCommand() {
66+
description := ""
67+
if e.State.PlacementPos != nil {
68+
description = e.State.PlacementPos.String()
69+
}
6670
entry := UiProtocolEntry{
67-
Timestamp: e.TimeProvider().UnixNano(),
68-
StageTime: e.State.StageTimeElapsed,
69-
Type: UiProtocolCommand,
70-
Name: string(e.State.Command),
71-
Team: e.State.CommandFor,
71+
Timestamp: e.TimeProvider().UnixNano(),
72+
StageTime: e.State.StageTimeElapsed,
73+
Type: UiProtocolCommand,
74+
Name: string(e.State.Command),
75+
Team: e.State.CommandFor,
76+
Description: description,
7277
}
7378
e.UiProtocol = append(e.UiProtocol, entry)
7479
}

src/components/events/Events.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020
</div>
2121
</b-modal>
2222

23+
<b-btn v-b-modal.place-ball-modal size="sm" variant="primary">Place ball</b-btn>
24+
<b-modal id="place-ball-modal"
25+
title="Place ball"
26+
:lazy="true">
27+
<PlaceBall/>
28+
<div slot="modal-footer">
29+
<!-- hide modal buttons -->
30+
</div>
31+
</b-modal>
32+
2333
<b-btn v-b-modal.event-behavior-modal size="sm" variant="primary">Configure Behaviors</b-btn>
2434
<b-modal id="event-behavior-modal"
2535
title="Game Event Behaviors"
@@ -37,10 +47,11 @@
3747
import EventTable from "./EventTable";
3848
import NewEvent from "./NewEvent";
3949
import EventBehavior from "./EventBehavior";
50+
import PlaceBall from "./PlaceBall";
4051
4152
export default {
4253
name: "Events",
43-
components: {EventBehavior, EventTable, NewEvent},
54+
components: {PlaceBall, EventBehavior, EventTable, NewEvent},
4455
data() {
4556
return {
4657
currentPage: 1,

src/components/events/PlaceBall.vue

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<template>
2+
<div>
3+
<TeamSelection :model="model" label="For: " :allow-unknown-team="false"/>
4+
<LocationSelection :model="model.location" label="Location [mm]: "/>
5+
<b-button variant="primary"
6+
@click="sendEvent()"
7+
:disabled="model.team === null || !ballLocationSet">
8+
Add
9+
</b-button>
10+
</div>
11+
</template>
12+
13+
<script>
14+
import EventAccordion from "./EventAccordion";
15+
import LocationSelection from "../common/LocationSelection";
16+
import TeamSelection from "../common/TeamSelection";
17+
import {convertStringLocation} from "../../refereeState";
18+
import {isNumeric} from "../../main";
19+
20+
export default {
21+
name: "PlaceBall",
22+
components: {EventAccordion,TeamSelection,LocationSelection},
23+
data() {
24+
return {
25+
model: {
26+
team: null,
27+
id: null,
28+
location: {x: 0.0, y: 0.0}
29+
}
30+
}
31+
},
32+
computed: {
33+
ballLocationSet() {
34+
return isNumeric(this.model.location.x)
35+
&& isNumeric(this.model.location.y)
36+
}
37+
},
38+
methods: {
39+
sendEvent: function () {
40+
this.$socket.sendObj({
41+
command: {
42+
forTeam: this.model.team,
43+
commandType: 'ballPlacement',
44+
location: convertStringLocation(this.model.location)
45+
}
46+
});
47+
this.$root.$emit('bv::hide::modal', 'place-ball-modal');
48+
}
49+
}
50+
}
51+
</script>
52+
53+
<style scoped>
54+
55+
</style>

src/main.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ library.add(faSignal);
3939
library.add(faCheckCircle);
4040
Vue.component('font-awesome-icon', FontAwesomeIcon);
4141

42+
43+
export let isNumeric = function (n) {
44+
return !isNaN(parseFloat(n)) && isFinite(n);
45+
};
46+
4247
let wsAddress;
4348
if (process.env.NODE_ENV === 'development') {
4449
// use the default backend port

0 commit comments

Comments
 (0)