Refactor rover attributes to add a name

This commit is contained in:
Marc Di Luzio 2020-06-06 16:52:30 +01:00
parent db38ad6091
commit 5e1f9b0d31
10 changed files with 43 additions and 72 deletions

View file

@ -134,7 +134,7 @@ func InnerMain(command string) error {
return fmt.Errorf("Server returned failure: %s", response.Error) return fmt.Errorf("Server returned failure: %s", response.Error)
} else { } else {
fmt.Printf("Spawned at position %+v\n", response.Position) fmt.Printf("Spawned rover with attributes %+v\n", response.Attributes)
} }
case "move": case "move":
@ -184,7 +184,7 @@ func InnerMain(command string) error {
return fmt.Errorf("Server returned failure: %s", response.Error) return fmt.Errorf("Server returned failure: %s", response.Error)
} else { } else {
fmt.Printf("position: %v\n", response.Position) fmt.Printf("attributes: %v\n", response.Attributes)
} }
default: default:

1
go.mod
View file

@ -7,4 +7,5 @@ require (
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/robfig/cron v1.2.0 github.com/robfig/cron v1.2.0
github.com/stretchr/testify v1.6.0 github.com/stretchr/testify v1.6.0
github.com/tjarratt/babble v0.0.0-20191209142150-eecdf8c2339d
) )

2
go.sum
View file

@ -11,6 +11,8 @@ github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfm
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho= github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tjarratt/babble v0.0.0-20191209142150-eecdf8c2339d h1:b7oHBI6TgTdCDuqTijsVldzlh+6cfQpdYLz1EKtCAoY=
github.com/tjarratt/babble v0.0.0-20191209142150-eecdf8c2339d/go.mod h1:O5hBrCGqzfb+8WyY8ico2AyQau7XQwAfEQeEQ5/5V9E=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -29,8 +29,8 @@ func TestCommand_Move(t *testing.T) {
// Tick the world // Tick the world
world.ExecuteCommandQueues() world.ExecuteCommandQueues()
newpos, err := world.RoverPosition(a) newatributes, err := world.RoverAttributes(a)
assert.NoError(t, err, "Failed to set position for rover") assert.NoError(t, err, "Failed to set position for rover")
pos.Add(Vector{0.0, duration * attribs.Speed}) // We should have moved duration*speed north pos.Add(Vector{0.0, duration * attribs.Speed}) // We should have moved duration*speed north
assert.Equal(t, pos, newpos, "Failed to correctly set position for rover") assert.Equal(t, pos, newatributes.Pos, "Failed to correctly set position for rover")
} }

View file

@ -5,6 +5,7 @@ import (
"sync" "sync"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/tjarratt/babble"
) )
// World describes a self contained universe and everything in it // World describes a self contained universe and everything in it
@ -22,27 +23,6 @@ type World struct {
cmdMutex sync.RWMutex cmdMutex sync.RWMutex
} }
// RoverAttributes contains attributes of a rover
type RoverAttributes struct {
// Speed represents the Speed that the rover will move per second
Speed int `json:"speed"`
// Range represents the distance the unit's radar can see
Range int `json:"range"`
}
// Rover describes a single rover in the world
type Rover struct {
// Id is a unique ID for this rover
Id uuid.UUID `json:"id"`
// Pos represents where this rover is in the world
Pos Vector `json:"pos"`
// Attributes represents the physical attributes of the rover
Attributes RoverAttributes `json:"attributes"`
}
// NewWorld creates a new world object // NewWorld creates a new world object
func NewWorld() *World { func NewWorld() *World {
return &World{ return &World{
@ -59,14 +39,14 @@ func (w *World) SpawnRover() uuid.UUID {
// Initialise the rover // Initialise the rover
rover := Rover{ rover := Rover{
Id: uuid.New(), Id: uuid.New(),
// TODO: Set this somehow
Pos: Vector{},
// TODO: Stop these being random numbers
Attributes: RoverAttributes{ Attributes: RoverAttributes{
Speed: 1.0, Speed: 1.0,
Range: 20.0, Range: 20.0,
Pos: Vector{},
// Set the name randomly
Name: babble.NewBabbler().Babble(),
}, },
} }
@ -101,25 +81,13 @@ func (w *World) RoverAttributes(id uuid.UUID) (RoverAttributes, error) {
} }
} }
// RoverPosition returns the position of a given rover
func (w *World) RoverPosition(id uuid.UUID) (Vector, error) {
w.worldMutex.RLock()
defer w.worldMutex.RUnlock()
if i, ok := w.Rovers[id]; ok {
return i.Pos, nil
} else {
return Vector{}, fmt.Errorf("no rover matching id")
}
}
// WarpRover sets an rovers position // WarpRover sets an rovers position
func (w *World) WarpRover(id uuid.UUID, pos Vector) error { func (w *World) WarpRover(id uuid.UUID, pos Vector) error {
w.worldMutex.Lock() w.worldMutex.Lock()
defer w.worldMutex.Unlock() defer w.worldMutex.Unlock()
if i, ok := w.Rovers[id]; ok { if i, ok := w.Rovers[id]; ok {
i.Pos = pos i.Attributes.Pos = pos
w.Rovers[id] = i w.Rovers[id] = i
return nil return nil
} else { } else {
@ -128,7 +96,7 @@ func (w *World) WarpRover(id uuid.UUID, pos Vector) error {
} }
// SetPosition sets an rovers position // SetPosition sets an rovers position
func (w *World) MoveRover(id uuid.UUID, bearing Direction) (Vector, error) { func (w *World) MoveRover(id uuid.UUID, bearing Direction) (RoverAttributes, error) {
w.worldMutex.Lock() w.worldMutex.Lock()
defer w.worldMutex.Unlock() defer w.worldMutex.Unlock()
@ -140,13 +108,13 @@ func (w *World) MoveRover(id uuid.UUID, bearing Direction) (Vector, error) {
move := bearing.Vector().Multiplied(distance) move := bearing.Vector().Multiplied(distance)
// Increment the position by the movement // Increment the position by the movement
i.Pos.Add(move) i.Attributes.Pos.Add(move)
// Set the rover values to the new ones // Set the rover values to the new ones
w.Rovers[id] = i w.Rovers[id] = i
return i.Pos, nil return i.Attributes, nil
} else { } else {
return Vector{}, fmt.Errorf("no rover matching id") return RoverAttributes{}, fmt.Errorf("no rover matching id")
} }
} }
@ -166,8 +134,8 @@ func (w *World) RadarFromRover(id uuid.UUID) (RadarDescription, error) {
// Gather nearby rovers within the range // Gather nearby rovers within the range
for _, r2 := range w.Rovers { for _, r2 := range w.Rovers {
if r1.Id != r2.Id && r1.Pos.Distance(r2.Pos) < float64(r1.Attributes.Range) { if r1.Id != r2.Id && r1.Attributes.Pos.Distance(r2.Attributes.Pos) < float64(r1.Attributes.Range) {
desc.Rovers = append(desc.Rovers, r2.Pos) desc.Rovers = append(desc.Rovers, r2.Attributes.Pos)
} }
} }

View file

@ -67,16 +67,16 @@ func TestWorld_GetSetMovePosition(t *testing.T) {
err = world.WarpRover(a, pos) err = world.WarpRover(a, pos)
assert.NoError(t, err, "Failed to set position for rover") assert.NoError(t, err, "Failed to set position for rover")
newpos, err := world.RoverPosition(a) newAttribs, err := world.RoverAttributes(a)
assert.NoError(t, err, "Failed to set position for rover") assert.NoError(t, err, "Failed to set position for rover")
assert.Equal(t, pos, newpos, "Failed to correctly set position for rover") assert.Equal(t, pos, newAttribs.Pos, "Failed to correctly set position for rover")
bearing := North bearing := North
duration := 1 duration := 1
newpos, err = world.MoveRover(a, bearing) newAttribs, err = world.MoveRover(a, bearing)
assert.NoError(t, err, "Failed to set position for rover") assert.NoError(t, err, "Failed to set position for rover")
pos.Add(Vector{0, attribs.Speed * duration}) // We should have move one unit of the speed north pos.Add(Vector{0, attribs.Speed * duration}) // We should have move one unit of the speed north
assert.Equal(t, pos, newpos, "Failed to correctly move position for rover") assert.Equal(t, pos, newAttribs.Pos, "Failed to correctly move position for rover")
} }
func TestWorld_RadarFromRover(t *testing.T) { func TestWorld_RadarFromRover(t *testing.T) {

View file

@ -66,8 +66,8 @@ type SpawnResponse struct {
Success bool `json:"success"` Success bool `json:"success"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
// The location of the spawned entity // The attributes of the spawned entity
Position game.Vector `json:"position"` Attributes game.RoverAttributes `json:"attributes"`
} }
// ============================== // ==============================
@ -122,6 +122,6 @@ type RoverResponse struct {
Success bool `json:"success"` Success bool `json:"success"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
// The set of positions for nearby rovers // The current position of this rover
Position game.Vector `json:"position"` Attributes game.RoverAttributes `json:"attributes"`
} }

View file

@ -126,14 +126,14 @@ func HandleSpawn(s *Server, vars map[string]string, b io.ReadCloser, w io.Writer
} else if id, err := uuid.Parse(id); err != nil { } else if id, err := uuid.Parse(id); err != nil {
response.Error = "Provided account ID was invalid" response.Error = "Provided account ID was invalid"
} else if pos, rover, err := s.SpawnRoverForAccount(id); err != nil { } else if attribs, rover, err := s.SpawnRoverForAccount(id); err != nil {
response.Error = err.Error() response.Error = err.Error()
} else { } else {
fmt.Printf("New rover spawned\taccount:%s\trover:%s\tpos:%+v\n", id, rover, pos) fmt.Printf("New rover spawned\taccount:%s\trover:%s\attributes:%+v\n", id, rover, attribs)
response.Success = true response.Success = true
response.Position = pos response.Attributes = attribs
} }
return response, nil return response, nil
@ -217,12 +217,12 @@ func HandleRover(s *Server, vars map[string]string, b io.ReadCloser, w io.Writer
} else if inst, err := s.accountant.GetRover(id); err != nil { } else if inst, err := s.accountant.GetRover(id); err != nil {
response.Error = fmt.Sprintf("Provided account has no rover: %s", err) response.Error = fmt.Sprintf("Provided account has no rover: %s", err)
} else if pos, err := s.world.RoverPosition(inst); err != nil { } else if attribs, err := s.world.RoverAttributes(inst); err != nil {
response.Error = fmt.Sprintf("Error getting radar from rover: %s", err) response.Error = fmt.Sprintf("Error getting radar from rover: %s", err)
} else { } else {
fmt.Printf("Responded with rover\taccount:%s\trover:%+v\n", id, pos) fmt.Printf("Responded with rover\taccount:%s\trover:%+v\n", id, attribs)
response.Position = pos response.Attributes = attribs
response.Success = true response.Success = true
} }

View file

@ -92,7 +92,7 @@ func TestHandleCommand(t *testing.T) {
// Spawn the rover rover for the account // Spawn the rover rover for the account
_, inst, err := s.SpawnRoverForAccount(a.Id) _, inst, err := s.SpawnRoverForAccount(a.Id)
pos, err := s.world.RoverPosition(inst) attribs, err := s.world.RoverAttributes(inst)
assert.NoError(t, err, "Couldn't get rover position") assert.NoError(t, err, "Couldn't get rover position")
data := rove.CommandData{ data := rove.CommandData{
@ -127,10 +127,10 @@ func TestHandleCommand(t *testing.T) {
// Tick the command queues to progress the move command // Tick the command queues to progress the move command
s.world.ExecuteCommandQueues() s.world.ExecuteCommandQueues()
pos2, err := s.world.RoverPosition(inst) attribs2, err := s.world.RoverAttributes(inst)
assert.NoError(t, err, "Couldn't get rover position") assert.NoError(t, err, "Couldn't get rover position")
pos.Add(game.Vector{X: 0.0, Y: attrib.Speed * 1}) // Should have moved north by the speed and duration attribs.Pos.Add(game.Vector{X: 0.0, Y: attrib.Speed * 1}) // Should have moved north by the speed and duration
assert.Equal(t, pos, pos2, "Rover should have moved by bearing") assert.Equal(t, attribs.Pos, attribs2.Pos, "Rover should have moved by bearing")
} }
func TestHandleRadar(t *testing.T) { func TestHandleRadar(t *testing.T) {

View file

@ -258,10 +258,10 @@ func (s *Server) wrapHandler(method string, handler Handler) func(w http.Respons
} }
// SpawnRoverForAccount spawns the rover rover for an account // SpawnRoverForAccount spawns the rover rover for an account
func (s *Server) SpawnRoverForAccount(accountid uuid.UUID) (game.Vector, uuid.UUID, error) { func (s *Server) SpawnRoverForAccount(accountid uuid.UUID) (game.RoverAttributes, uuid.UUID, error) {
inst := s.world.SpawnRover() inst := s.world.SpawnRover()
if pos, err := s.world.RoverPosition(inst); err != nil { if attribs, err := s.world.RoverAttributes(inst); err != nil {
return game.Vector{}, uuid.UUID{}, fmt.Errorf("No position found for created rover") return game.RoverAttributes{}, uuid.UUID{}, fmt.Errorf("No attributes found for created rover")
} else { } else {
if err := s.accountant.AssignRover(accountid, inst); err != nil { if err := s.accountant.AssignRover(accountid, inst); err != nil {
@ -270,9 +270,9 @@ func (s *Server) SpawnRoverForAccount(accountid uuid.UUID) (game.Vector, uuid.UU
fmt.Printf("Failed to destroy rover after failed rover assign: %s", err) fmt.Printf("Failed to destroy rover after failed rover assign: %s", err)
} }
return game.Vector{}, uuid.UUID{}, err return game.RoverAttributes{}, uuid.UUID{}, err
} else { } else {
return pos, inst, nil return attribs, inst, nil
} }
} }
} }