chore: refactor structure
This commit is contained in:
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/bitmap"
|
"github.com/iliadenisov/galaxy/internal/bitmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBitVectorSize(t *testing.T) {
|
func TestBitVectorSize(t *testing.T) {
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/repo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Repo interface {
|
||||||
|
// Lock must be called before any repository operations
|
||||||
|
Lock() error
|
||||||
|
|
||||||
|
// Release must be called after first and only repository operation
|
||||||
|
Release() error
|
||||||
|
|
||||||
|
// SaveTurn stores just generated new turn
|
||||||
|
SaveTurn(uint, game.Game) error
|
||||||
|
|
||||||
|
// SaveState stores current game state updated between turns
|
||||||
|
SaveState(game.Game) error
|
||||||
|
|
||||||
|
// LoadState retrieves game current state
|
||||||
|
LoadState() (game.Game, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ctrl struct {
|
||||||
|
param Param
|
||||||
|
Repo Repo
|
||||||
|
}
|
||||||
|
|
||||||
|
type Param struct {
|
||||||
|
StoragePath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewController(configure func(*Param)) (*Ctrl, error) {
|
||||||
|
c := &Param{
|
||||||
|
StoragePath: ".",
|
||||||
|
}
|
||||||
|
if configure != nil {
|
||||||
|
configure(c)
|
||||||
|
}
|
||||||
|
r, err := repo.NewFileRepo(c.StoragePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Ctrl{
|
||||||
|
param: *c,
|
||||||
|
Repo: r,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Ctrl) ExecuteInit(consumer func(Repo)) error {
|
||||||
|
if err := c.Repo.Lock(); err != nil {
|
||||||
|
return fmt.Errorf("execute: lock failed: %s", err)
|
||||||
|
}
|
||||||
|
consumer(c.Repo)
|
||||||
|
return c.Repo.Release()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Ctrl) Execute(consumer func(Repo, game.Game)) error {
|
||||||
|
if err := c.Repo.Lock(); err != nil {
|
||||||
|
return fmt.Errorf("execute: lock failed: %s", err)
|
||||||
|
}
|
||||||
|
g, err := c.Repo.LoadState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
consumer(c.Repo, g)
|
||||||
|
return c.Repo.Release()
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package game
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -6,11 +6,11 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/iliadenisov/galaxy/pkg/generator"
|
"github.com/iliadenisov/galaxy/internal/generator"
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newGame(r Repo, races []string) (uuid.UUID, error) {
|
func NewGame(r Repo, races []string) (uuid.UUID, error) {
|
||||||
m, err := generator.Generate(func(ms *generator.MapSetting) {
|
m, err := generator.Generate(func(ms *generator.MapSetting) {
|
||||||
ms.Players = uint32(len(races))
|
ms.Players = uint32(len(races))
|
||||||
})
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package game
|
package controller_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -6,9 +6,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
"github.com/iliadenisov/galaxy/pkg/repo"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/iliadenisov/galaxy/pkg/util"
|
"github.com/iliadenisov/galaxy/internal/repo"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ func TestNewGame(t *testing.T) {
|
|||||||
races[i] = fmt.Sprintf("race_%02d", i)
|
races[i] = fmt.Sprintf("race_%02d", i)
|
||||||
}
|
}
|
||||||
assert.NoError(t, r.Lock())
|
assert.NoError(t, r.Lock())
|
||||||
gameID, err := newGame(r, races)
|
gameID, err := controller.NewGame(r, races)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.FileExists(t, filepath.Join(root, "state.json"))
|
assert.FileExists(t, filepath.Join(root, "state.json"))
|
||||||
@@ -14,6 +14,7 @@ const (
|
|||||||
ErrDeleteShipTypePlanetProduction = 5001
|
ErrDeleteShipTypePlanetProduction = 5001
|
||||||
ErrDeleteSciencePlanetProduction = 5002
|
ErrDeleteSciencePlanetProduction = 5002
|
||||||
ErrMergeShipTypeNotEqual = 5003
|
ErrMergeShipTypeNotEqual = 5003
|
||||||
|
ErrJoinFleetGroupNumberNotEnough = 5004
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -83,6 +84,8 @@ func GenericErrorText(code int) string {
|
|||||||
return "Invalid Production type"
|
return "Invalid Production type"
|
||||||
case ErrMergeShipTypeNotEqual:
|
case ErrMergeShipTypeNotEqual:
|
||||||
return "Source and target ship types are not the same"
|
return "Source and target ship types are not the same"
|
||||||
|
case ErrJoinFleetGroupNumberNotEnough:
|
||||||
|
return "Not enough ships in the group to join a fleet"
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("Undescribed error with code %d", code)
|
return fmt.Sprintf("Undescribed error with code %d", code)
|
||||||
}
|
}
|
||||||
@@ -67,3 +67,7 @@ func NewProductionInvalidError(arg ...any) error {
|
|||||||
func NewMergeShipTypeNotEqualError(arg ...any) error {
|
func NewMergeShipTypeNotEqualError(arg ...any) error {
|
||||||
return newGenericError(ErrMergeShipTypeNotEqual, arg...)
|
return newGenericError(ErrMergeShipTypeNotEqual, arg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewJoinFleetGroupNumberNotEnoughError(arg ...any) error {
|
||||||
|
return newGenericError(ErrJoinFleetGroupNumberNotEnough, arg...)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JoinEqualGroups(configure func(*controller.Param), race string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = joinEqualGroups(r, g, race)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinEqualGroups(r controller.Repo, g game.Game, race string) error {
|
||||||
|
if err := g.JoinEqualGroups(race); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package game_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/game"
|
||||||
|
mg "github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJoinEqualGroups(t *testing.T) {
|
||||||
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
|
err := game.JoinEqualGroups(p, "race_01")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RenamePlanet(configure func(*controller.Param), race string, number int, name string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = renamePlanet(r, g, race, number, name)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func renamePlanet(r controller.Repo, g game.Game, race string, number int, name string) error {
|
||||||
|
if err := g.RenamePlanet(race, number, name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
@@ -4,16 +4,17 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
"github.com/iliadenisov/galaxy/internal/game"
|
||||||
mg "github.com/iliadenisov/galaxy/pkg/model/game"
|
mg "github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRenamePlanet(t *testing.T) {
|
func TestRenamePlanet(t *testing.T) {
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
cg := g()
|
cg := g()
|
||||||
var number int
|
var number int
|
||||||
var owner uuid.UUID
|
var owner uuid.UUID
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PlanetProduction(configure func(*controller.Param), race string, planetNumber int, prodType, subject string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = planetProduction(r, g, race, planetNumber, prodType, subject)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func planetProduction(r controller.Repo, g game.Game, race string, planetNumber int, prodType, subject string) error {
|
||||||
|
if err := g.PlanetProduction(race, planetNumber, prodType, subject); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateScience(configure func(*controller.Param), race, typeName string, drive, weapons, shields, cargo float64) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = createScience(r, g, race, typeName, drive, weapons, shields, cargo)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func createScience(r controller.Repo, g game.Game, race, typeName string, d, w, s, c float64) error {
|
||||||
|
if err := g.CreateScience(race, typeName, d, w, s, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteScience(configure func(*controller.Param), race, typeName string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = deleteScience(r, g, race, typeName)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteScience(r controller.Repo, g game.Game, race, typeName string) error {
|
||||||
|
if err := g.DeleteScience(race, typeName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
@@ -4,16 +4,18 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
|
||||||
mg "github.com/iliadenisov/galaxy/pkg/model/game"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/game"
|
||||||
|
mg "github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateScience(t *testing.T) {
|
func TestCreateScience(t *testing.T) {
|
||||||
race := "race_01"
|
race := "race_01"
|
||||||
typeName := "First Step"
|
typeName := "First Step"
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
err := game.DeleteScience(p, race, typeName)
|
err := game.DeleteScience(p, race, typeName)
|
||||||
assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityNotExists))
|
assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
err = game.CreateScience(p, unknownRaceName, " "+typeName+" ", 1, 0, 0, 0) // TODO: test on dead race
|
err = game.CreateScience(p, unknownRaceName, " "+typeName+" ", 1, 0, 0, 0) // TODO: test on dead race
|
||||||
@@ -72,7 +74,7 @@ func TestCreateScienceValidation(t *testing.T) {
|
|||||||
{typeName, 0, 0, 0, -1, e.GenericErrorText(e.ErrInputCargoValue)},
|
{typeName, 0, 0, 0, -1, e.GenericErrorText(e.ErrInputCargoValue)},
|
||||||
{typeName, 0, 1, 1, -1, e.GenericErrorText(e.ErrInputCargoValue)},
|
{typeName, 0, 1, 1, -1, e.GenericErrorText(e.ErrInputCargoValue)},
|
||||||
}
|
}
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
for i, tc := range table {
|
for i, tc := range table {
|
||||||
if tc.err == "" {
|
if tc.err == "" {
|
||||||
err := game.CreateScience(p, race, tc.name+strconv.Itoa(i), tc.d, tc.w, tc.s, tc.c)
|
err := game.CreateScience(p, race, tc.name+strconv.Itoa(i), tc.d, tc.w, tc.s, tc.c)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateShipType(configure func(*controller.Param), race, typeName string, drive, weapons, shields, cargo float64, armament int) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = createShipType(r, g, race, typeName, drive, weapons, shields, cargo, armament)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func createShipType(r controller.Repo, g game.Game, race, typeName string, d, w, s, c float64, a int) error {
|
||||||
|
if err := g.CreateShipType(race, typeName, d, w, s, c, a); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MergeShipType(configure func(*controller.Param), race, source, target string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = mergeShipType(r, g, race, source, target)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeShipType(r controller.Repo, g game.Game, race, source, target string) error {
|
||||||
|
if err := g.MergeShipType(race, source, target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteShipType(configure func(*controller.Param), race, typeName string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) {
|
||||||
|
err = deleteShipType(r, g, race, typeName)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteShipType(r controller.Repo, g game.Game, race, typeName string) error {
|
||||||
|
if err := g.DeleteShipType(race, typeName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
@@ -4,16 +4,18 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
|
||||||
mg "github.com/iliadenisov/galaxy/pkg/model/game"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/game"
|
||||||
|
mg "github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateShipType(t *testing.T) {
|
func TestCreateShipType(t *testing.T) {
|
||||||
race := "race_01"
|
race := "race_01"
|
||||||
typeName := "Drone"
|
typeName := "Drone"
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
err := game.DeleteShipType(p, race, typeName)
|
err := game.DeleteShipType(p, race, typeName)
|
||||||
assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityNotExists))
|
assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
err = game.CreateShipType(p, unknownRaceName, " "+typeName+" ", 1, 0, 0, 0, 0) // TODO: test on dead race
|
err = game.CreateShipType(p, unknownRaceName, " "+typeName+" ", 1, 0, 0, 0, 0) // TODO: test on dead race
|
||||||
@@ -77,7 +79,7 @@ func TestCreateShipTypeValidation(t *testing.T) {
|
|||||||
{typeName, 0, 1, 0, 0, 0, e.GenericErrorText(e.ErrInputShipTypeWeaponsAndArmamentValue)},
|
{typeName, 0, 1, 0, 0, 0, e.GenericErrorText(e.ErrInputShipTypeWeaponsAndArmamentValue)},
|
||||||
{typeName, 0, 0, 0, 0, 1, e.GenericErrorText(e.ErrInputShipTypeWeaponsAndArmamentValue)},
|
{typeName, 0, 0, 0, 0, 1, e.GenericErrorText(e.ErrInputShipTypeWeaponsAndArmamentValue)},
|
||||||
}
|
}
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
for i, tc := range table {
|
for i, tc := range table {
|
||||||
if tc.err == "" {
|
if tc.err == "" {
|
||||||
err := game.CreateShipType(p, race, tc.name+strconv.Itoa(i), tc.d, tc.w, tc.s, tc.c, tc.a)
|
err := game.CreateShipType(p, race, tc.name+strconv.Itoa(i), tc.d, tc.w, tc.s, tc.c, tc.a)
|
||||||
@@ -94,7 +96,7 @@ func TestCreateShipTypeValidation(t *testing.T) {
|
|||||||
|
|
||||||
func TestMergeShipType(t *testing.T) {
|
func TestMergeShipType(t *testing.T) {
|
||||||
race := "race_01"
|
race := "race_01"
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
err := game.CreateShipType(p, race, "Drone", 1, 0, 0, 0, 0)
|
err := game.CreateShipType(p, race, "Drone", 1, 0, 0, 0, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = game.CreateShipType(p, race, "Spy", 1, 0, 0, 0, 0)
|
err = game.CreateShipType(p, race, "Spy", 1, 0, 0, 0, 0)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DeclareWar(configure func(*controller.Param), from, to string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) { err = updateRelation(r, g, from, to, game.RelationWar) })
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeclarePeace(configure func(*controller.Param), from, to string) (err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.Execute(func(r controller.Repo, g game.Game) { err = updateRelation(r, g, from, to, game.RelationPeace) })
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateRelation(r controller.Repo, g game.Game, hostRace, opponentRace string, rel game.Relation) error {
|
||||||
|
if err := g.UpdateRelation(hostRace, opponentRace, rel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.SaveState(g)
|
||||||
|
}
|
||||||
@@ -3,15 +3,16 @@ package game_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
"github.com/iliadenisov/galaxy/internal/game"
|
||||||
mg "github.com/iliadenisov/galaxy/pkg/model/game"
|
mg "github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeclarePeaceAndWarSingle(t *testing.T) {
|
func TestDeclarePeaceAndWarSingle(t *testing.T) {
|
||||||
g(t, func(f func(*game.Param), g func() mg.Game) {
|
g(t, func(f func(*controller.Param), g func() mg.Game) {
|
||||||
hostRace := "race_05"
|
hostRace := "race_05"
|
||||||
opponentRace := "race_01"
|
opponentRace := "race_01"
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ func TestDeclarePeaceAndWarSingle(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeclarePeaceAndWarAll(t *testing.T) {
|
func TestDeclarePeaceAndWarAll(t *testing.T) {
|
||||||
g(t, func(f func(*game.Param), g func() mg.Game) {
|
g(t, func(f func(*controller.Param), g func() mg.Game) {
|
||||||
hostRace := "race_07"
|
hostRace := "race_07"
|
||||||
|
|
||||||
for i := range testRaceCount {
|
for i := range testRaceCount {
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadState(configure func(*controller.Param)) (g game.Game, err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) { c.ExecuteInit(func(r controller.Repo) { g, err = c.Repo.LoadState() }) })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateGame(configure func(*controller.Param), races []string) (gameID uuid.UUID, err error) {
|
||||||
|
control(configure, func(c *controller.Ctrl) {
|
||||||
|
c.ExecuteInit(func(r controller.Repo) { gameID, err = controller.NewGame(r, races) })
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func control(configure func(*controller.Param), consumer func(*controller.Ctrl)) error {
|
||||||
|
c, err := controller.NewController(configure)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
consumer(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -4,9 +4,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
mg "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/util"
|
"github.com/iliadenisov/galaxy/internal/game"
|
||||||
|
mg "github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
|
"github.com/iliadenisov/galaxy/internal/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,21 +22,21 @@ func raceNum(i int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestComposeGame(t *testing.T) {
|
func TestComposeGame(t *testing.T) {
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
g(t, func(p func(*controller.Param), g func() mg.Game) {
|
||||||
_, err := game.GenerateGame(p, []string{"r1", "r2"})
|
_, err := game.GenerateGame(p, []string{"r1", "r2"})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.ErrorContains(t, err, "state for turn 0 already saved")
|
assert.ErrorContains(t, err, "state for turn 0 already saved")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func g(t *testing.T, f func(p func(*game.Param), g func() mg.Game)) {
|
func g(t *testing.T, f func(p func(*controller.Param), g func() mg.Game)) {
|
||||||
root, cleanup := util.CreateWorkDir(t)
|
root, cleanup := util.CreateWorkDir(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
races := make([]string, testRaceCount)
|
races := make([]string, testRaceCount)
|
||||||
for i := range testRaceCount {
|
for i := range testRaceCount {
|
||||||
races[i] = raceNum(i)
|
races[i] = raceNum(i)
|
||||||
}
|
}
|
||||||
p := func(p *game.Param) { p.StoragePath = root }
|
p := func(p *controller.Param) { p.StoragePath = root }
|
||||||
_, err := game.GenerateGame(p, races)
|
_, err := game.GenerateGame(p, races)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
assert.FailNow(t, "g: ComposeGame", err)
|
assert.FailNow(t, "g: ComposeGame", err)
|
||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/generator"
|
"github.com/iliadenisov/galaxy/internal/generator"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/generator/plotter"
|
"github.com/iliadenisov/galaxy/internal/generator/plotter"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Map struct {
|
type Map struct {
|
||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/number"
|
"github.com/iliadenisov/galaxy/internal/number"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
g "github.com/iliadenisov/galaxy/pkg/generator"
|
g "github.com/iliadenisov/galaxy/internal/generator"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/bitmap"
|
"github.com/iliadenisov/galaxy/internal/bitmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Plotter struct {
|
type Plotter struct {
|
||||||
@@ -3,7 +3,7 @@ package plotter_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/generator/plotter"
|
"github.com/iliadenisov/galaxy/internal/generator/plotter"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewPlotter(t *testing.T) {
|
func TestNewPlotter(t *testing.T) {
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fleet struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
OwnerID uuid.UUID `json:"ownerId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Hello! Wanna know fleet's speed? Good. Implement & test this func first.
|
||||||
|
func (g Game) FleetSpeed(fl Fleet) float64 {
|
||||||
|
result := math.MaxFloat64
|
||||||
|
for sg := range g.ShipGroups {
|
||||||
|
if g.ShipGroups[sg].FleetID == nil || *g.ShipGroups[sg].FleetID != fl.ID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
st := g.mustShipType(g.ShipGroups[sg].TypeID)
|
||||||
|
typeSpeed := g.ShipGroups[sg].Speed(st)
|
||||||
|
if typeSpeed < result {
|
||||||
|
result = typeSpeed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g Game) JoinShipGroupToFleet(raceName, fleetName string, group, count uint) error {
|
||||||
|
ri, err := g.raceIndex(raceName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return g.joinShipGroupToFleetInternal(ri, fleetName, group, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g Game) joinShipGroupToFleetInternal(ri int, fleetName string, group, count uint) (err error) {
|
||||||
|
name, ok := validateTypeName(fleetName)
|
||||||
|
if !ok {
|
||||||
|
return e.NewEntityTypeNameValidationError("%q", name)
|
||||||
|
}
|
||||||
|
sgi := -1
|
||||||
|
var maxIndex uint
|
||||||
|
for i, sg := range g.listShipGroups(ri) {
|
||||||
|
if sgi < 0 && sg.Index == group {
|
||||||
|
sgi = i
|
||||||
|
}
|
||||||
|
if sg.Index > maxIndex {
|
||||||
|
maxIndex = sg.Index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sgi < 0 {
|
||||||
|
return e.NewEntityNotExistsError("group #%d", group)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.ShipGroups[sgi].Number < count {
|
||||||
|
return e.NewJoinFleetGroupNumberNotEnoughError("%d<%d", g.ShipGroups[sgi].Number, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fi := g.fleetIndex(ri, name)
|
||||||
|
if fi < 0 {
|
||||||
|
fi, err = g.createFleet(ri, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.ShipGroups[sgi].Number != count && count > 0 {
|
||||||
|
newGroup := g.ShipGroups[sgi]
|
||||||
|
newGroup.Number -= count
|
||||||
|
g.ShipGroups[sgi].Number = count
|
||||||
|
newGroup.Index = maxIndex + 1
|
||||||
|
g.ShipGroups = append(g.ShipGroups, newGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.ShipGroups[sgi].FleetID = &g.Fleets[fi].ID
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g Game) fleetIndex(ri int, name string) int {
|
||||||
|
return slices.IndexFunc(g.Fleets, func(f Fleet) bool { return f.OwnerID == g.Race[ri].ID && f.Name == name })
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g Game) createFleet(ri int, name string) (int, error) {
|
||||||
|
n, ok := validateTypeName(name)
|
||||||
|
if !ok {
|
||||||
|
return 0, e.NewEntityTypeNameValidationError("%q", n)
|
||||||
|
}
|
||||||
|
if fl := g.fleetIndex(ri, n); fl >= 0 {
|
||||||
|
return 0, e.NewEntityTypeNameDuplicateError("fleet %w", g.Fleets[fl].Name)
|
||||||
|
}
|
||||||
|
g.Fleets = append(g.Fleets, Fleet{
|
||||||
|
ID: uuid.New(),
|
||||||
|
OwnerID: g.Race[ri].ID,
|
||||||
|
Name: n,
|
||||||
|
})
|
||||||
|
return len(g.Fleets) - 1, nil
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
@@ -6,6 +6,6 @@ func (g *Game) CreateShips(ri int, shipTypeName string, planetNumber int, quanti
|
|||||||
return g.createShips(ri, shipTypeName, planetNumber, quantity)
|
return g.createShips(ri, shipTypeName, planetNumber, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Game) ListShipGroups(ri int) iter.Seq[ShipGroup] {
|
func (g Game) ListShipGroups(ri int) iter.Seq2[int, ShipGroup] {
|
||||||
return g.listShipGroups(ri)
|
return g.listShipGroups(ri)
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,13 @@ package game
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"iter"
|
"iter"
|
||||||
|
"maps"
|
||||||
"math"
|
"math"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/pkg/number"
|
"github.com/iliadenisov/galaxy/internal/number"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CargoType string
|
type CargoType string
|
||||||
@@ -120,7 +121,7 @@ func (g *Game) JoinEqualGroups(raceName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) joinEqualGroupsInternal(ri int) {
|
func (g *Game) joinEqualGroupsInternal(ri int) {
|
||||||
shipGroups := slices.Collect(g.listShipGroups(ri))
|
shipGroups := slices.Collect(maps.Values(maps.Collect(g.listShipGroups(ri))))
|
||||||
origin := len(shipGroups)
|
origin := len(shipGroups)
|
||||||
if origin < 2 {
|
if origin < 2 {
|
||||||
return
|
return
|
||||||
@@ -155,7 +156,7 @@ func (g *Game) createShips(ri int, shipTypeName string, planetNumber int, quanti
|
|||||||
}
|
}
|
||||||
|
|
||||||
var maxIndex uint
|
var maxIndex uint
|
||||||
for sg := range g.listShipGroups(ri) {
|
for _, sg := range g.listShipGroups(ri) {
|
||||||
if sg.Index > maxIndex {
|
if sg.Index > maxIndex {
|
||||||
maxIndex = sg.Index
|
maxIndex = sg.Index
|
||||||
}
|
}
|
||||||
@@ -175,11 +176,11 @@ func (g *Game) createShips(ri int, shipTypeName string, planetNumber int, quanti
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Game) listShipGroups(ri int) iter.Seq[ShipGroup] {
|
func (g Game) listShipGroups(ri int) iter.Seq2[int, ShipGroup] {
|
||||||
return func(yield func(ShipGroup) bool) {
|
return func(yield func(int, ShipGroup) bool) {
|
||||||
for sg := range g.ShipGroups {
|
for sg := range g.ShipGroups {
|
||||||
if g.ShipGroups[sg].OwnerID == g.Race[ri].ID {
|
if g.ShipGroups[sg].OwnerID == g.Race[ri].ID {
|
||||||
if !yield(g.ShipGroups[sg]) {
|
if !yield(sg, g.ShipGroups[sg]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package game_test
|
package game_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"iter"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
gg "github.com/iliadenisov/galaxy/pkg/game"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -296,9 +297,9 @@ func TestJoinEqualGroups(t *testing.T) {
|
|||||||
Height: 10,
|
Height: 10,
|
||||||
Planet: make([]game.Planet, 3),
|
Planet: make([]game.Planet, 3),
|
||||||
}
|
}
|
||||||
g.Map.Planet[0] = gg.NewPlanet(0, "Planet_0", g.Race[0].ID, 0, 0, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil))
|
g.Map.Planet[0] = controller.NewPlanet(0, "Planet_0", g.Race[0].ID, 0, 0, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil))
|
||||||
g.Map.Planet[1] = gg.NewPlanet(1, "Planet_1", g.Race[1].ID, 1, 1, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil))
|
g.Map.Planet[1] = controller.NewPlanet(1, "Planet_1", g.Race[1].ID, 1, 1, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil))
|
||||||
g.Map.Planet[2] = gg.NewPlanet(1, "Planet_2", g.Race[0].ID, 2, 2, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil))
|
g.Map.Planet[2] = controller.NewPlanet(1, "Planet_2", g.Race[0].ID, 2, 2, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil))
|
||||||
|
|
||||||
err := g.CreateShipType("Race_0", "R0_Gunship", 60, 30, 100, 0, 3)
|
err := g.CreateShipType("Race_0", "R0_Gunship", 60, 30, 100, 0, 3)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -317,48 +318,48 @@ func TestJoinEqualGroups(t *testing.T) {
|
|||||||
|
|
||||||
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 1) // 1 -> 2
|
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 1) // 1 -> 2
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 1)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 1)
|
||||||
|
|
||||||
err = g.CreateShips(1, "R1_Freighter", 1, 1)
|
err = g.CreateShips(1, "R1_Freighter", 1, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(1)), 1)
|
assert.Len(t, collectGroups(g.ListShipGroups(1)), 1)
|
||||||
|
|
||||||
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 6) // (2)
|
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 6) // (2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 2)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 2)
|
||||||
|
|
||||||
err = g.CreateShips(raceIdx, "R0_Gunship", 0, 2) // (3)
|
err = g.CreateShips(raceIdx, "R0_Gunship", 0, 2) // (3)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 3)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 3)
|
||||||
|
|
||||||
err = g.CreateShips(1, "R1_Gunship", 1, 1)
|
err = g.CreateShips(1, "R1_Gunship", 1, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(1)), 2)
|
assert.Len(t, collectGroups(g.ListShipGroups(1)), 2)
|
||||||
|
|
||||||
g.Race[raceIdx].Drive = 1.5
|
g.Race[raceIdx].Drive = 1.5
|
||||||
err = g.CreateShips(raceIdx, "R0_Gunship", 0, 9) // 4 -> 6
|
err = g.CreateShips(raceIdx, "R0_Gunship", 0, 9) // 4 -> 6
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 4)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 4)
|
||||||
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 7) // 5 -> 7
|
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 7) // 5 -> 7
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 5)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 5)
|
||||||
err = g.CreateShips(raceIdx, "R0_Gunship", 0, 4) // (6)
|
err = g.CreateShips(raceIdx, "R0_Gunship", 0, 4) // (6)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 6)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 6)
|
||||||
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 4) // (7)
|
err = g.CreateShips(raceIdx, "R0_Freighter", 0, 4) // (7)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 7)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 7)
|
||||||
|
|
||||||
g.Race[1].Shields = 2.0
|
g.Race[1].Shields = 2.0
|
||||||
err = g.CreateShips(1, "R1_Freighter", 1, 1)
|
err = g.CreateShips(1, "R1_Freighter", 1, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(1)), 3)
|
assert.Len(t, collectGroups(g.ListShipGroups(1)), 3)
|
||||||
|
|
||||||
err = g.JoinEqualGroups("Race_0")
|
err = g.JoinEqualGroups("Race_0")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(1)), 3)
|
assert.Len(t, collectGroups(g.ListShipGroups(1)), 3)
|
||||||
assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 4)
|
assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 4)
|
||||||
|
|
||||||
shipTypeID := func(ri int, name string) uuid.UUID {
|
shipTypeID := func(ri int, name string) uuid.UUID {
|
||||||
st := slices.IndexFunc(g.Race[ri].ShipTypes, func(v game.ShipType) bool { return v.Name == name })
|
st := slices.IndexFunc(g.Race[ri].ShipTypes, func(v game.ShipType) bool { return v.Name == name })
|
||||||
@@ -369,7 +370,7 @@ func TestJoinEqualGroups(t *testing.T) {
|
|||||||
return g.Race[ri].ShipTypes[st].ID
|
return g.Race[ri].ShipTypes[st].ID
|
||||||
}
|
}
|
||||||
|
|
||||||
for sg := range g.ListShipGroups(raceIdx) {
|
for _, sg := range g.ListShipGroups(raceIdx) {
|
||||||
switch {
|
switch {
|
||||||
case sg.TypeID == shipTypeID(raceIdx, "R0_Freighter") && sg.Drive == 1.1:
|
case sg.TypeID == shipTypeID(raceIdx, "R0_Freighter") && sg.Drive == 1.1:
|
||||||
assert.Equal(t, uint(7), sg.Number)
|
assert.Equal(t, uint(7), sg.Number)
|
||||||
@@ -388,3 +389,11 @@ func TestJoinEqualGroups(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func collectGroups(i iter.Seq2[int, game.ShipGroup]) []game.ShipGroup {
|
||||||
|
result := make([]game.ShipGroup, 0)
|
||||||
|
for _, sg := range i {
|
||||||
|
result = append(result, sg)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UnidentifiedPlanet struct {
|
type UnidentifiedPlanet struct {
|
||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlanetProduction string
|
type PlanetProduction string
|
||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Science struct {
|
type Science struct {
|
||||||
@@ -74,6 +74,9 @@ func (g Game) createScienceInternal(ri int, name string, d, w, s, c float64) err
|
|||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityTypeNameValidationError("%q", n)
|
return e.NewEntityTypeNameValidationError("%q", n)
|
||||||
}
|
}
|
||||||
|
if sc := slices.IndexFunc(g.Race[ri].Sciences, func(s Science) bool { return s.Name == n }); sc >= 0 {
|
||||||
|
return e.NewEntityTypeNameDuplicateError("science %w", g.Race[ri].Sciences[sc].Name)
|
||||||
|
}
|
||||||
if d < 0 {
|
if d < 0 {
|
||||||
return e.NewDriveValueError(d)
|
return e.NewDriveValueError(d)
|
||||||
}
|
}
|
||||||
@@ -90,9 +93,6 @@ func (g Game) createScienceInternal(ri int, name string, d, w, s, c float64) err
|
|||||||
if sum != 1 {
|
if sum != 1 {
|
||||||
return e.NewScienceSumValuesError("D=%f W=%f S=%f C=%f sum=%f", d, w, s, c, sum)
|
return e.NewScienceSumValuesError("D=%f W=%f S=%f C=%f sum=%f", d, w, s, c, sum)
|
||||||
}
|
}
|
||||||
if sc := slices.IndexFunc(g.Race[ri].Sciences, func(s Science) bool { return s.Name == n }); sc >= 0 {
|
|
||||||
return e.NewEntityTypeNameDuplicateError("science %w", g.Race[ri].Sciences[sc].Name)
|
|
||||||
}
|
|
||||||
g.Race[ri].Sciences = append(g.Race[ri].Sciences, Science{
|
g.Race[ri].Sciences = append(g.Race[ri].Sciences, Science{
|
||||||
ID: uuid.New(),
|
ID: uuid.New(),
|
||||||
ScienceReport: ScienceReport{
|
ScienceReport: ScienceReport{
|
||||||
@@ -2,11 +2,10 @@ package game
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShipTypeReport struct {
|
type ShipTypeReport struct {
|
||||||
@@ -28,11 +27,6 @@ type ShipTypeReportForeign struct {
|
|||||||
ShipTypeReport
|
ShipTypeReport
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fleet struct {
|
|
||||||
OwnerID uuid.UUID `json:"ownerId"`
|
|
||||||
ShipGroups []ShipGroup `json:"group"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st ShipType) Equal(o ShipType) bool {
|
func (st ShipType) Equal(o ShipType) bool {
|
||||||
return st.Drive == o.Drive &&
|
return st.Drive == o.Drive &&
|
||||||
st.Weapons == o.Weapons &&
|
st.Weapons == o.Weapons &&
|
||||||
@@ -60,18 +54,6 @@ func (st ShipType) ProductionCost() (mat float64, pop float64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test this
|
|
||||||
func (g Game) FleetSpeed(fl *Fleet) float64 {
|
|
||||||
result := math.MaxFloat64
|
|
||||||
for _, sg := range fl.ShipGroups {
|
|
||||||
st := g.mustShipType(sg.TypeID)
|
|
||||||
if sg.Speed(st) < result {
|
|
||||||
result = sg.Speed(st)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g Game) mustShipType(id uuid.UUID) *ShipType {
|
func (g Game) mustShipType(id uuid.UUID) *ShipType {
|
||||||
for ri := range g.Race {
|
for ri := range g.Race {
|
||||||
if st := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == id }); st >= 0 {
|
if st := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == id }); st >= 0 {
|
||||||
@@ -3,7 +3,7 @@ package game_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/util"
|
"github.com/iliadenisov/galaxy/internal/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/iliadenisov/galaxy/pkg/util"
|
"github.com/iliadenisov/galaxy/internal/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ package repo
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"encoding"
|
"encoding"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
e "github.com/iliadenisov/galaxy/pkg/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/pkg/repo/fs"
|
"github.com/iliadenisov/galaxy/internal/repo/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewStorageError(err error) error {
|
func NewStorageError(err error) error {
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
func JoinEqualGroups(configure func(*Param), race string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = joinEqualGroups(r, g, race)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func joinEqualGroups(r Repo, g game.Game, race string) error {
|
|
||||||
if err := g.JoinEqualGroups(race); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package game_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
|
||||||
mg "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestJoinEqualGroups(t *testing.T) {
|
|
||||||
g(t, func(p func(*game.Param), g func() mg.Game) {
|
|
||||||
err := game.JoinEqualGroups(p, "race_01")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
func RenamePlanet(configure func(*Param), race string, number int, name string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = renamePlanet(r, g, race, number, name)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func renamePlanet(r Repo, g game.Game, race string, number int, name string) error {
|
|
||||||
if err := g.RenamePlanet(race, number, name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
func PlanetProduction(configure func(*Param), race string, planetNumber int, prodType, subject string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = planetProduction(r, g, race, planetNumber, prodType, subject)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func planetProduction(r Repo, g game.Game, race string, planetNumber int, prodType, subject string) error {
|
|
||||||
if err := g.PlanetProduction(race, planetNumber, prodType, subject); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
func CreateScience(configure func(*Param), race, typeName string, drive, weapons, shields, cargo float64) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = createScience(r, g, race, typeName, drive, weapons, shields, cargo)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func createScience(r Repo, g game.Game, race, typeName string, d, w, s, c float64) error {
|
|
||||||
if err := g.CreateScience(race, typeName, d, w, s, c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteScience(configure func(*Param), race, typeName string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = deleteScience(r, g, race, typeName)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteScience(r Repo, g game.Game, race, typeName string) error {
|
|
||||||
if err := g.DeleteScience(race, typeName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
func CreateShipType(configure func(*Param), race, typeName string, drive, weapons, shields, cargo float64, armament int) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = createShipType(r, g, race, typeName, drive, weapons, shields, cargo, armament)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func createShipType(r Repo, g game.Game, race, typeName string, d, w, s, c float64, a int) error {
|
|
||||||
if err := g.CreateShipType(race, typeName, d, w, s, c, a); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MergeShipType(configure func(*Param), race, source, target string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = mergeShipType(r, g, race, source, target)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func mergeShipType(r Repo, g game.Game, race, source, target string) error {
|
|
||||||
if err := g.MergeShipType(race, source, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteShipType(configure func(*Param), race, typeName string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) {
|
|
||||||
err = deleteShipType(r, g, race, typeName)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteShipType(r Repo, g game.Game, race, typeName string) error {
|
|
||||||
if err := g.DeleteShipType(race, typeName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
func DeclareWar(configure func(*Param), from, to string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) { err = updateRelation(r, g, from, to, game.RelationWar) })
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeclarePeace(configure func(*Param), from, to string) (err error) {
|
|
||||||
control(configure, func(c *ctrl) {
|
|
||||||
c.execute(func(r Repo, g game.Game) { err = updateRelation(r, g, from, to, game.RelationPeace) })
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateRelation(r Repo, g game.Game, hostRace, opponentRace string, rel game.Relation) error {
|
|
||||||
if err := g.UpdateRelation(hostRace, opponentRace, rel); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.SaveState(g)
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ctrl struct {
|
|
||||||
param Param
|
|
||||||
repo Repo
|
|
||||||
}
|
|
||||||
|
|
||||||
type Param struct {
|
|
||||||
StoragePath string
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadState(configure func(*Param)) (g game.Game, err error) {
|
|
||||||
control(configure, func(c *ctrl) { c.executeInit(func(r Repo) { g, err = c.repo.LoadState() }) })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GenerateGame(configure func(*Param), races []string) (gameID uuid.UUID, err error) {
|
|
||||||
control(configure, func(c *ctrl) { c.executeInit(func(r Repo) { gameID, err = newGame(r, races) }) })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func newController(configure func(*Param)) (*ctrl, error) {
|
|
||||||
c := &Param{
|
|
||||||
StoragePath: ".",
|
|
||||||
}
|
|
||||||
if configure != nil {
|
|
||||||
configure(c)
|
|
||||||
}
|
|
||||||
r, err := repo.NewFileRepo(c.StoragePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ctrl{
|
|
||||||
param: *c,
|
|
||||||
repo: r,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func control(configure func(*Param), consumer func(*ctrl)) error {
|
|
||||||
c, err := newController(configure)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
consumer(c)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctrl) executeInit(consumer func(Repo)) error {
|
|
||||||
if err := c.repo.Lock(); err != nil {
|
|
||||||
return fmt.Errorf("execute: lock failed: %s", err)
|
|
||||||
}
|
|
||||||
consumer(c.repo)
|
|
||||||
return c.repo.Release()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctrl) execute(consumer func(Repo, game.Game)) error {
|
|
||||||
if err := c.repo.Lock(); err != nil {
|
|
||||||
return fmt.Errorf("execute: lock failed: %s", err)
|
|
||||||
}
|
|
||||||
g, err := c.repo.LoadState()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
consumer(c.repo, g)
|
|
||||||
return c.repo.Release()
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "github.com/iliadenisov/galaxy/pkg/model/game"
|
|
||||||
|
|
||||||
type Repo interface {
|
|
||||||
// Lock must be called before any repository operations
|
|
||||||
Lock() error
|
|
||||||
|
|
||||||
// Release must be called after first and only repository operation
|
|
||||||
Release() error
|
|
||||||
|
|
||||||
// SaveTurn stores just generated new turn
|
|
||||||
SaveTurn(uint, game.Game) error
|
|
||||||
|
|
||||||
// SaveState stores current game state updated between turns
|
|
||||||
SaveState(game.Game) error
|
|
||||||
|
|
||||||
// LoadState retrieves game current state
|
|
||||||
LoadState() (game.Game, error)
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
type Command struct {
|
|
||||||
FromRace string
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommandAlly struct {
|
|
||||||
Command
|
|
||||||
ToRace string
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommandWar struct {
|
|
||||||
Command
|
|
||||||
ToRace string
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user