Huge Instance -> Rover refactor, for clarification
This commit is contained in:
parent
33f25a7414
commit
0fbad15c01
10 changed files with 96 additions and 96 deletions
|
@ -16,8 +16,8 @@ type Account struct {
|
|||
// Id represents a unique ID per account and is set one registered
|
||||
Id uuid.UUID `json:"id"`
|
||||
|
||||
// Primary represents the primary instance that this account owns
|
||||
Primary uuid.UUID `json:"primary"`
|
||||
// Rover represents the rover that this account owns
|
||||
Rover uuid.UUID `json:"rover"`
|
||||
}
|
||||
|
||||
// Represents the accountant data to store
|
||||
|
@ -58,12 +58,12 @@ func (a *Accountant) RegisterAccount(name string) (acc Account, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// AssignPrimary assigns primary ownership of an instance to an account
|
||||
func (a *Accountant) AssignPrimary(account uuid.UUID, instance uuid.UUID) error {
|
||||
// AssignRover assigns rover ownership of an rover to an account
|
||||
func (a *Accountant) AssignRover(account uuid.UUID, rover uuid.UUID) error {
|
||||
|
||||
// Find the account matching the ID
|
||||
if this, ok := a.Accounts[account]; ok {
|
||||
this.Primary = instance
|
||||
this.Rover = rover
|
||||
a.Accounts[account] = this
|
||||
} else {
|
||||
return fmt.Errorf("no account found for id: %s", account)
|
||||
|
@ -72,11 +72,11 @@ func (a *Accountant) AssignPrimary(account uuid.UUID, instance uuid.UUID) error
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetPrimary gets the primary instance for the account
|
||||
func (a *Accountant) GetPrimary(account uuid.UUID) (uuid.UUID, error) {
|
||||
// GetRover gets the rover rover for the account
|
||||
func (a *Accountant) GetRover(account uuid.UUID) (uuid.UUID, error) {
|
||||
// Find the account matching the ID
|
||||
if this, ok := a.Accounts[account]; ok {
|
||||
return this.Primary, nil
|
||||
return this.Rover, nil
|
||||
}
|
||||
return uuid.UUID{}, fmt.Errorf("no account found for id: %s", account)
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ func TestAccountant_RegisterAccount(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAccountant_AssignGetPrimary(t *testing.T) {
|
||||
func TestAccountant_AssignGetRover(t *testing.T) {
|
||||
accountant := NewAccountant()
|
||||
if len(accountant.Accounts) != 0 {
|
||||
t.Error("New accountant created with non-zero account number")
|
||||
|
@ -62,14 +62,14 @@ func TestAccountant_AssignGetPrimary(t *testing.T) {
|
|||
|
||||
inst := uuid.New()
|
||||
|
||||
err = accountant.AssignPrimary(a.Id, inst)
|
||||
err = accountant.AssignRover(a.Id, inst)
|
||||
if err != nil {
|
||||
t.Error("Failed to set primary for created account")
|
||||
} else if accountant.Accounts[a.Id].Primary != inst {
|
||||
t.Error("Primary for assigned account is incorrect")
|
||||
} else if id, err := accountant.GetPrimary(a.Id); err != nil {
|
||||
t.Error("Failed to get primary for account")
|
||||
t.Error("Failed to set rover for created account")
|
||||
} else if accountant.Accounts[a.Id].Rover != inst {
|
||||
t.Error("Rover for assigned account is incorrect")
|
||||
} else if id, err := accountant.GetRover(a.Id); err != nil {
|
||||
t.Error("Failed to get rover for account")
|
||||
} else if id != inst {
|
||||
t.Error("Fetched primary is incorrect for account")
|
||||
t.Error("Fetched rover is incorrect for account")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ package game
|
|||
|
||||
import "github.com/google/uuid"
|
||||
|
||||
// A command is simply a function that acts on the a given instance in the world
|
||||
// A command is simply a function that acts on the a given rover in the world
|
||||
type Command func() error
|
||||
|
||||
// CommandMove will move the instance in question
|
||||
// CommandMove will move the rover in question
|
||||
func (w *World) CommandMove(id uuid.UUID, bearing float64, duration int64) Command {
|
||||
return func() error {
|
||||
// TODO: Calculate the move itself
|
||||
|
@ -19,6 +19,6 @@ func (w *World) CommandMove(id uuid.UUID, bearing float64, duration int64) Comma
|
|||
// TODO: Two spawn commands with the same id could trigger a fail later on, we should prevent that somehow
|
||||
func (w *World) CommandSpawn(id uuid.UUID) Command {
|
||||
return func() error {
|
||||
return w.Spawn(id)
|
||||
return w.SpawnRover(id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,15 +14,15 @@ func TestCommand_Spawn(t *testing.T) {
|
|||
spawnCommand := world.CommandSpawn(a)
|
||||
assert.NoError(t, world.Execute(spawnCommand), "Failed to execute spawn command")
|
||||
|
||||
instance, ok := world.Instances[a]
|
||||
assert.True(t, ok, "No new instance in world")
|
||||
assert.Equal(t, a, instance.Id, "New instance has incorrect id")
|
||||
rover, ok := world.Rovers[a]
|
||||
assert.True(t, ok, "No new rover in world")
|
||||
assert.Equal(t, a, rover.Id, "New rover has incorrect id")
|
||||
}
|
||||
|
||||
func TestCommand_Move(t *testing.T) {
|
||||
world := NewWorld()
|
||||
a := uuid.New()
|
||||
assert.NoError(t, world.Spawn(a), "Failed to spawn")
|
||||
assert.NoError(t, world.SpawnRover(a), "Failed to spawn")
|
||||
|
||||
pos := Vector{
|
||||
X: 1.0,
|
||||
|
@ -30,7 +30,7 @@ func TestCommand_Move(t *testing.T) {
|
|||
}
|
||||
|
||||
err := world.SetPosition(a, pos)
|
||||
assert.NoError(t, err, "Failed to set position for instance")
|
||||
assert.NoError(t, err, "Failed to set position for rover")
|
||||
|
||||
// TODO: Test the bearing/duration movement
|
||||
/*
|
||||
|
@ -39,8 +39,8 @@ func TestCommand_Move(t *testing.T) {
|
|||
assert.NoError(t, world.Execute(moveCommand), "Failed to execute move command")
|
||||
|
||||
newpos, err := world.GetPosition(a)
|
||||
assert.NoError(t, err, "Failed to set position for instance")
|
||||
assert.NoError(t, err, "Failed to set position for rover")
|
||||
pos.Add(move)
|
||||
assert.Equal(t, pos, newpos, "Failed to correctly set position for instance")
|
||||
assert.Equal(t, pos, newpos, "Failed to correctly set position for rover")
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -8,19 +8,19 @@ import (
|
|||
|
||||
// World describes a self contained universe and everything in it
|
||||
type World struct {
|
||||
// Instances is a map of all the instances in the game
|
||||
Instances map[uuid.UUID]Instance `json:"instances"`
|
||||
// Rovers is a id->data map of all the rovers in the game
|
||||
Rovers map[uuid.UUID]Rover `json:"rovers"`
|
||||
}
|
||||
|
||||
// Instance describes a single entity or instance of an entity in the world
|
||||
type Instance struct {
|
||||
// Id is a unique ID for this instance
|
||||
// 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 instance is in the world
|
||||
// Pos represents where this rover is in the world
|
||||
Pos Vector `json:"pos"`
|
||||
|
||||
// Speed represents the Speed that the instance will move per second
|
||||
// Speed represents the Speed that the rover will move per second
|
||||
Speed float64 `json:"speed"`
|
||||
|
||||
// Sight represents the distance the unit can see
|
||||
|
@ -30,65 +30,65 @@ type Instance struct {
|
|||
// NewWorld creates a new world object
|
||||
func NewWorld() *World {
|
||||
return &World{
|
||||
Instances: make(map[uuid.UUID]Instance),
|
||||
Rovers: make(map[uuid.UUID]Rover),
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn adds an instance to the game
|
||||
func (w *World) Spawn(id uuid.UUID) error {
|
||||
if _, ok := w.Instances[id]; ok {
|
||||
return fmt.Errorf("instance with id %s already exists in world", id)
|
||||
// SpawnRover adds an rover to the game
|
||||
func (w *World) SpawnRover(id uuid.UUID) error {
|
||||
if _, ok := w.Rovers[id]; ok {
|
||||
return fmt.Errorf("rover with id %s already exists in world", id)
|
||||
}
|
||||
|
||||
// Initialise the instance
|
||||
instance := Instance{
|
||||
// Initialise the rover
|
||||
rover := Rover{
|
||||
Id: id,
|
||||
}
|
||||
|
||||
// Append the instance to the list
|
||||
w.Instances[id] = instance
|
||||
// Append the rover to the list
|
||||
w.Rovers[id] = rover
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Removes an instance from the game
|
||||
func (w *World) DestroyInstance(id uuid.UUID) error {
|
||||
if _, ok := w.Instances[id]; ok {
|
||||
delete(w.Instances, id)
|
||||
// Removes an rover from the game
|
||||
func (w *World) DestroyRover(id uuid.UUID) error {
|
||||
if _, ok := w.Rovers[id]; ok {
|
||||
delete(w.Rovers, id)
|
||||
} else {
|
||||
return fmt.Errorf("no instance matching id")
|
||||
return fmt.Errorf("no rover matching id")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPosition returns the position of a given instance
|
||||
// GetPosition returns the position of a given rover
|
||||
func (w World) GetPosition(id uuid.UUID) (Vector, error) {
|
||||
if i, ok := w.Instances[id]; ok {
|
||||
if i, ok := w.Rovers[id]; ok {
|
||||
return i.Pos, nil
|
||||
} else {
|
||||
return Vector{}, fmt.Errorf("no instance matching id")
|
||||
return Vector{}, fmt.Errorf("no rover matching id")
|
||||
}
|
||||
}
|
||||
|
||||
// SetPosition sets an instances position
|
||||
// SetPosition sets an rovers position
|
||||
func (w *World) SetPosition(id uuid.UUID, pos Vector) error {
|
||||
if i, ok := w.Instances[id]; ok {
|
||||
if i, ok := w.Rovers[id]; ok {
|
||||
i.Pos = pos
|
||||
w.Instances[id] = i
|
||||
w.Rovers[id] = i
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("no instance matching id")
|
||||
return fmt.Errorf("no rover matching id")
|
||||
}
|
||||
}
|
||||
|
||||
// SetPosition sets an instances position
|
||||
// SetPosition sets an rovers position
|
||||
func (w *World) MovePosition(id uuid.UUID, vec Vector) (Vector, error) {
|
||||
if i, ok := w.Instances[id]; ok {
|
||||
if i, ok := w.Rovers[id]; ok {
|
||||
i.Pos.Add(vec)
|
||||
w.Instances[id] = i
|
||||
w.Rovers[id] = i
|
||||
return i.Pos, nil
|
||||
} else {
|
||||
return Vector{}, fmt.Errorf("no instance matching id")
|
||||
return Vector{}, fmt.Errorf("no rover matching id")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,43 +15,43 @@ func TestNewWorld(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestWorld_CreateInstance(t *testing.T) {
|
||||
func TestWorld_CreateRover(t *testing.T) {
|
||||
world := NewWorld()
|
||||
a := uuid.New()
|
||||
b := uuid.New()
|
||||
assert.NoError(t, world.Spawn(a), "Failed to spawn")
|
||||
assert.NoError(t, world.Spawn(b), "Failed to spawn")
|
||||
assert.NoError(t, world.SpawnRover(a), "Failed to spawn")
|
||||
assert.NoError(t, world.SpawnRover(b), "Failed to spawn")
|
||||
|
||||
// Basic duplicate check
|
||||
if a == b {
|
||||
t.Errorf("Created identical instances")
|
||||
} else if len(world.Instances) != 2 {
|
||||
t.Errorf("Incorrect number of instances created")
|
||||
t.Errorf("Created identical rovers")
|
||||
} else if len(world.Rovers) != 2 {
|
||||
t.Errorf("Incorrect number of rovers created")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorld_DestroyInstance(t *testing.T) {
|
||||
func TestWorld_DestroyRover(t *testing.T) {
|
||||
world := NewWorld()
|
||||
a := uuid.New()
|
||||
b := uuid.New()
|
||||
assert.NoError(t, world.Spawn(a), "Failed to spawn")
|
||||
assert.NoError(t, world.Spawn(b), "Failed to spawn")
|
||||
assert.NoError(t, world.SpawnRover(a), "Failed to spawn")
|
||||
assert.NoError(t, world.SpawnRover(b), "Failed to spawn")
|
||||
|
||||
err := world.DestroyInstance(a)
|
||||
assert.NoError(t, err, "Error returned from instance destroy")
|
||||
err := world.DestroyRover(a)
|
||||
assert.NoError(t, err, "Error returned from rover destroy")
|
||||
|
||||
// Basic duplicate check
|
||||
if len(world.Instances) != 1 {
|
||||
t.Error("Too many instances left in world")
|
||||
} else if _, ok := world.Instances[b]; !ok {
|
||||
t.Error("Remaining instance is incorrect")
|
||||
if len(world.Rovers) != 1 {
|
||||
t.Error("Too many rovers left in world")
|
||||
} else if _, ok := world.Rovers[b]; !ok {
|
||||
t.Error("Remaining rover is incorrect")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorld_GetSetMovePosition(t *testing.T) {
|
||||
world := NewWorld()
|
||||
a := uuid.New()
|
||||
assert.NoError(t, world.Spawn(a), "Failed to spawn")
|
||||
assert.NoError(t, world.SpawnRover(a), "Failed to spawn")
|
||||
|
||||
pos := Vector{
|
||||
X: 1.0,
|
||||
|
@ -59,14 +59,14 @@ func TestWorld_GetSetMovePosition(t *testing.T) {
|
|||
}
|
||||
|
||||
err := world.SetPosition(a, pos)
|
||||
assert.NoError(t, err, "Failed to set position for instance")
|
||||
assert.NoError(t, err, "Failed to set position for rover")
|
||||
|
||||
newpos, err := world.GetPosition(a)
|
||||
assert.NoError(t, err, "Failed to set position for instance")
|
||||
assert.Equal(t, pos, newpos, "Failed to correctly set position for instance")
|
||||
assert.NoError(t, err, "Failed to set position for rover")
|
||||
assert.Equal(t, pos, newpos, "Failed to correctly set position for rover")
|
||||
|
||||
newpos, err = world.MovePosition(a, pos)
|
||||
assert.NoError(t, err, "Failed to set position for instance")
|
||||
assert.NoError(t, err, "Failed to set position for rover")
|
||||
pos.Add(pos)
|
||||
assert.Equal(t, pos, newpos, "Failed to correctly move position for instance")
|
||||
assert.Equal(t, pos, newpos, "Failed to correctly move position for rover")
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ type RegisterResponse struct {
|
|||
|
||||
// ==============================
|
||||
// API: /spawn method: POST
|
||||
// Spawns the primary entity for an account
|
||||
// Responds with the position of said entity
|
||||
// Spawns the rover for an account
|
||||
// Responds with the position of said rover
|
||||
|
||||
// SpawnData is the data to be sent for the spawn command
|
||||
type SpawnData struct {
|
||||
|
|
|
@ -130,8 +130,8 @@ func HandleSpawn(s *Server, b io.ReadCloser, w io.Writer) error {
|
|||
// log the data sent
|
||||
fmt.Printf("\tspawn data: %v\n", data)
|
||||
|
||||
// Create a new instance
|
||||
if pos, _, err := s.SpawnPrimaryForAccount(id); err != nil {
|
||||
// Create a new rover
|
||||
if pos, _, err := s.SpawnRoverForAccount(id); err != nil {
|
||||
response.Error = err.Error()
|
||||
} else {
|
||||
response.Success = true
|
||||
|
@ -168,8 +168,8 @@ func HandleCommands(s *Server, b io.ReadCloser, w io.Writer) error {
|
|||
} else if id, err := uuid.Parse(data.Id); err != nil {
|
||||
response.Error = fmt.Sprintf("Provided account ID was invalid: %s", err)
|
||||
|
||||
} else if inst, err := s.accountant.GetPrimary(id); err != nil {
|
||||
response.Error = fmt.Sprintf("Provided account has no primary: %s", err)
|
||||
} else if inst, err := s.accountant.GetRover(id); err != nil {
|
||||
response.Error = fmt.Sprintf("Provided account has no rover: %s", err)
|
||||
|
||||
} else {
|
||||
// log the data sent
|
||||
|
|
|
@ -77,8 +77,8 @@ func TestHandleCommands(t *testing.T) {
|
|||
a, err := s.accountant.RegisterAccount("test")
|
||||
assert.NoError(t, err, "Error registering account")
|
||||
|
||||
// Spawn the primary instance for the account
|
||||
_, inst, err := s.SpawnPrimaryForAccount(a.Id)
|
||||
// Spawn the rover rover for the account
|
||||
_, inst, err := s.SpawnRoverForAccount(a.Id)
|
||||
|
||||
data := CommandsData{
|
||||
Id: a.Id.String(),
|
||||
|
@ -107,7 +107,7 @@ func TestHandleCommands(t *testing.T) {
|
|||
}
|
||||
|
||||
if _, err := s.world.GetPosition(inst); err != nil {
|
||||
t.Error("Couldn't get position for the primary instance")
|
||||
t.Error("Couldn't get position for the rover rover")
|
||||
}
|
||||
|
||||
// TODO: Check position is correct
|
||||
|
|
|
@ -161,18 +161,18 @@ func (s *Server) wrapHandler(method string, handler Handler) func(w http.Respons
|
|||
}
|
||||
}
|
||||
|
||||
// SpawnPrimaryForAccount spawns the primary instance for an account
|
||||
func (s *Server) SpawnPrimaryForAccount(accountid uuid.UUID) (game.Vector, uuid.UUID, error) {
|
||||
// SpawnRoverForAccount spawns the rover rover for an account
|
||||
func (s *Server) SpawnRoverForAccount(accountid uuid.UUID) (game.Vector, uuid.UUID, error) {
|
||||
inst := uuid.New()
|
||||
s.world.Spawn(inst)
|
||||
s.world.SpawnRover(inst)
|
||||
if pos, err := s.world.GetPosition(inst); err != nil {
|
||||
return game.Vector{}, uuid.UUID{}, fmt.Errorf("No position found for created instance")
|
||||
return game.Vector{}, uuid.UUID{}, fmt.Errorf("No position found for created rover")
|
||||
|
||||
} else {
|
||||
if err := s.accountant.AssignPrimary(accountid, inst); err != nil {
|
||||
// Try and clear up the instance
|
||||
if err := s.world.DestroyInstance(inst); err != nil {
|
||||
fmt.Printf("Failed to destroy instance after failed primary assign: %s", err)
|
||||
if err := s.accountant.AssignRover(accountid, inst); err != nil {
|
||||
// Try and clear up the rover
|
||||
if err := s.world.DestroyRover(inst); err != nil {
|
||||
fmt.Printf("Failed to destroy rover after failed rover assign: %s", err)
|
||||
}
|
||||
|
||||
return game.Vector{}, uuid.UUID{}, err
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue