diff --git a/pkg/bitmap/assets_test/circle_case_00.txt b/internal/bitmap/assets_test/circle_case_00.txt similarity index 100% rename from pkg/bitmap/assets_test/circle_case_00.txt rename to internal/bitmap/assets_test/circle_case_00.txt diff --git a/pkg/bitmap/assets_test/circle_case_01.txt b/internal/bitmap/assets_test/circle_case_01.txt similarity index 100% rename from pkg/bitmap/assets_test/circle_case_01.txt rename to internal/bitmap/assets_test/circle_case_01.txt diff --git a/pkg/bitmap/assets_test/circle_case_02.txt b/internal/bitmap/assets_test/circle_case_02.txt similarity index 100% rename from pkg/bitmap/assets_test/circle_case_02.txt rename to internal/bitmap/assets_test/circle_case_02.txt diff --git a/pkg/bitmap/assets_test/circle_case_03.txt b/internal/bitmap/assets_test/circle_case_03.txt similarity index 100% rename from pkg/bitmap/assets_test/circle_case_03.txt rename to internal/bitmap/assets_test/circle_case_03.txt diff --git a/pkg/bitmap/assets_test/circle_case_04.txt b/internal/bitmap/assets_test/circle_case_04.txt similarity index 100% rename from pkg/bitmap/assets_test/circle_case_04.txt rename to internal/bitmap/assets_test/circle_case_04.txt diff --git a/pkg/bitmap/bitmap.go b/internal/bitmap/bitmap.go similarity index 100% rename from pkg/bitmap/bitmap.go rename to internal/bitmap/bitmap.go diff --git a/pkg/bitmap/bitmap_test.go b/internal/bitmap/bitmap_test.go similarity index 99% rename from pkg/bitmap/bitmap_test.go rename to internal/bitmap/bitmap_test.go index d294ddc..22104bb 100644 --- a/pkg/bitmap/bitmap_test.go +++ b/internal/bitmap/bitmap_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/iliadenisov/galaxy/pkg/bitmap" + "github.com/iliadenisov/galaxy/internal/bitmap" ) func TestBitVectorSize(t *testing.T) { diff --git a/pkg/bitmap/export_test.go b/internal/bitmap/export_test.go similarity index 100% rename from pkg/bitmap/export_test.go rename to internal/bitmap/export_test.go diff --git a/internal/controller/controller.go b/internal/controller/controller.go new file mode 100644 index 0000000..33a3ff8 --- /dev/null +++ b/internal/controller/controller.go @@ -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() +} diff --git a/pkg/game/generator.go b/internal/controller/generate.go similarity index 95% rename from pkg/game/generator.go rename to internal/controller/generate.go index bf37990..ddb42d7 100644 --- a/pkg/game/generator.go +++ b/internal/controller/generate.go @@ -1,4 +1,4 @@ -package game +package controller import ( "fmt" @@ -6,11 +6,11 @@ import ( "slices" "github.com/google/uuid" - "github.com/iliadenisov/galaxy/pkg/generator" - "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/generator" + "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) { ms.Players = uint32(len(races)) }) diff --git a/pkg/game/generator_test.go b/internal/controller/generate_test.go similarity index 82% rename from pkg/game/generator_test.go rename to internal/controller/generate_test.go index 176a11b..d8e2b9b 100644 --- a/pkg/game/generator_test.go +++ b/internal/controller/generate_test.go @@ -1,4 +1,4 @@ -package game +package controller_test import ( "fmt" @@ -6,9 +6,10 @@ import ( "testing" "github.com/google/uuid" - "github.com/iliadenisov/galaxy/pkg/model/game" - "github.com/iliadenisov/galaxy/pkg/repo" - "github.com/iliadenisov/galaxy/pkg/util" + "github.com/iliadenisov/galaxy/internal/controller" + "github.com/iliadenisov/galaxy/internal/model/game" + "github.com/iliadenisov/galaxy/internal/repo" + "github.com/iliadenisov/galaxy/internal/util" "github.com/stretchr/testify/assert" ) @@ -25,7 +26,7 @@ func TestNewGame(t *testing.T) { races[i] = fmt.Sprintf("race_%02d", i) } assert.NoError(t, r.Lock()) - gameID, err := newGame(r, races) + gameID, err := controller.NewGame(r, races) assert.NoError(t, err) assert.FileExists(t, filepath.Join(root, "state.json")) diff --git a/pkg/error/generic.go b/internal/error/generic.go similarity index 95% rename from pkg/error/generic.go rename to internal/error/generic.go index 1c2761e..f3e16e4 100644 --- a/pkg/error/generic.go +++ b/internal/error/generic.go @@ -14,6 +14,7 @@ const ( ErrDeleteShipTypePlanetProduction = 5001 ErrDeleteSciencePlanetProduction = 5002 ErrMergeShipTypeNotEqual = 5003 + ErrJoinFleetGroupNumberNotEnough = 5004 ) const ( @@ -83,6 +84,8 @@ func GenericErrorText(code int) string { return "Invalid Production type" case ErrMergeShipTypeNotEqual: return "Source and target ship types are not the same" + case ErrJoinFleetGroupNumberNotEnough: + return "Not enough ships in the group to join a fleet" default: return fmt.Sprintf("Undescribed error with code %d", code) } diff --git a/pkg/error/generic_test.go b/internal/error/generic_test.go similarity index 100% rename from pkg/error/generic_test.go rename to internal/error/generic_test.go diff --git a/pkg/error/input.go b/internal/error/input.go similarity index 93% rename from pkg/error/input.go rename to internal/error/input.go index 1abd291..32ffe7b 100644 --- a/pkg/error/input.go +++ b/internal/error/input.go @@ -67,3 +67,7 @@ func NewProductionInvalidError(arg ...any) error { func NewMergeShipTypeNotEqualError(arg ...any) error { return newGenericError(ErrMergeShipTypeNotEqual, arg...) } + +func NewJoinFleetGroupNumberNotEnoughError(arg ...any) error { + return newGenericError(ErrJoinFleetGroupNumberNotEnough, arg...) +} diff --git a/pkg/error/repo.go b/internal/error/repo.go similarity index 100% rename from pkg/error/repo.go rename to internal/error/repo.go diff --git a/pkg/error/state.go b/internal/error/state.go similarity index 100% rename from pkg/error/state.go rename to internal/error/state.go diff --git a/internal/game/cmd_group.go b/internal/game/cmd_group.go new file mode 100644 index 0000000..ad6f4c6 --- /dev/null +++ b/internal/game/cmd_group.go @@ -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) +} diff --git a/internal/game/cmd_group_test.go b/internal/game/cmd_group_test.go new file mode 100644 index 0000000..ce9b539 --- /dev/null +++ b/internal/game/cmd_group_test.go @@ -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) + }) +} diff --git a/internal/game/cmd_planet.go b/internal/game/cmd_planet.go new file mode 100644 index 0000000..8b46619 --- /dev/null +++ b/internal/game/cmd_planet.go @@ -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) +} diff --git a/pkg/game/cmd_planet_test.go b/internal/game/cmd_planet_test.go similarity index 86% rename from pkg/game/cmd_planet_test.go rename to internal/game/cmd_planet_test.go index c513cd7..bade304 100644 --- a/pkg/game/cmd_planet_test.go +++ b/internal/game/cmd_planet_test.go @@ -4,16 +4,17 @@ import ( "slices" "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/iliadenisov/galaxy/pkg/game" - mg "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/game" + mg "github.com/iliadenisov/galaxy/internal/model/game" "github.com/stretchr/testify/assert" ) 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() var number int var owner uuid.UUID diff --git a/internal/game/cmd_production.go b/internal/game/cmd_production.go new file mode 100644 index 0000000..d245d6c --- /dev/null +++ b/internal/game/cmd_production.go @@ -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) +} diff --git a/internal/game/cmd_science.go b/internal/game/cmd_science.go new file mode 100644 index 0000000..e1ef2d9 --- /dev/null +++ b/internal/game/cmd_science.go @@ -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) +} diff --git a/pkg/game/cmd_science_test.go b/internal/game/cmd_science_test.go similarity index 90% rename from pkg/game/cmd_science_test.go rename to internal/game/cmd_science_test.go index d3c2908..4120416 100644 --- a/pkg/game/cmd_science_test.go +++ b/internal/game/cmd_science_test.go @@ -4,16 +4,18 @@ import ( "strconv" "testing" - e "github.com/iliadenisov/galaxy/pkg/error" - "github.com/iliadenisov/galaxy/pkg/game" - mg "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/controller" + + 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" ) func TestCreateScience(t *testing.T) { race := "race_01" 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) assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityNotExists)) 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, 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 { if tc.err == "" { err := game.CreateScience(p, race, tc.name+strconv.Itoa(i), tc.d, tc.w, tc.s, tc.c) diff --git a/internal/game/cmd_ship_type.go b/internal/game/cmd_ship_type.go new file mode 100644 index 0000000..782a002 --- /dev/null +++ b/internal/game/cmd_ship_type.go @@ -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) +} diff --git a/pkg/game/cmd_ship_type_test.go b/internal/game/cmd_ship_type_test.go similarity index 91% rename from pkg/game/cmd_ship_type_test.go rename to internal/game/cmd_ship_type_test.go index d633994..96cdbe7 100644 --- a/pkg/game/cmd_ship_type_test.go +++ b/internal/game/cmd_ship_type_test.go @@ -4,16 +4,18 @@ import ( "strconv" "testing" - e "github.com/iliadenisov/galaxy/pkg/error" - "github.com/iliadenisov/galaxy/pkg/game" - mg "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/controller" + + 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" ) func TestCreateShipType(t *testing.T) { race := "race_01" 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) assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityNotExists)) 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, 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 { if tc.err == "" { 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) { 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) assert.NoError(t, err) err = game.CreateShipType(p, race, "Spy", 1, 0, 0, 0, 0) diff --git a/internal/game/cmd_war_peace.go b/internal/game/cmd_war_peace.go new file mode 100644 index 0000000..1690d9a --- /dev/null +++ b/internal/game/cmd_war_peace.go @@ -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) +} diff --git a/pkg/game/cmd_war_peace_test.go b/internal/game/cmd_war_peace_test.go similarity index 85% rename from pkg/game/cmd_war_peace_test.go rename to internal/game/cmd_war_peace_test.go index 58c4d69..7941f93 100644 --- a/pkg/game/cmd_war_peace_test.go +++ b/internal/game/cmd_war_peace_test.go @@ -3,15 +3,16 @@ package game_test import ( "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" - mg "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/game" + mg "github.com/iliadenisov/galaxy/internal/model/game" "github.com/stretchr/testify/assert" ) 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" opponentRace := "race_01" @@ -37,7 +38,7 @@ func TestDeclarePeaceAndWarSingle(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" for i := range testRaceCount { diff --git a/internal/game/controller.go b/internal/game/controller.go new file mode 100644 index 0000000..b4949b7 --- /dev/null +++ b/internal/game/controller.go @@ -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 +} diff --git a/pkg/game/controller_test.go b/internal/game/controller_test.go similarity index 67% rename from pkg/game/controller_test.go rename to internal/game/controller_test.go index e76d074..bb832e1 100644 --- a/pkg/game/controller_test.go +++ b/internal/game/controller_test.go @@ -4,9 +4,11 @@ import ( "fmt" "testing" - "github.com/iliadenisov/galaxy/pkg/game" - mg "github.com/iliadenisov/galaxy/pkg/model/game" - "github.com/iliadenisov/galaxy/pkg/util" + "github.com/iliadenisov/galaxy/internal/controller" + + "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" ) @@ -20,21 +22,21 @@ func raceNum(i int) string { } 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"}) assert.Error(t, err) 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) defer cleanup() races := make([]string, testRaceCount) for i := range testRaceCount { 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) if err != nil { assert.FailNow(t, "g: ComposeGame", err) diff --git a/pkg/generator/generator.go b/internal/generator/generator.go similarity index 100% rename from pkg/generator/generator.go rename to internal/generator/generator.go diff --git a/pkg/generator/generator_test.go b/internal/generator/generator_test.go similarity index 98% rename from pkg/generator/generator_test.go rename to internal/generator/generator_test.go index ccd0251..c80d425 100644 --- a/pkg/generator/generator_test.go +++ b/internal/generator/generator_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/iliadenisov/galaxy/pkg/generator" + "github.com/iliadenisov/galaxy/internal/generator" "github.com/stretchr/testify/assert" ) diff --git a/pkg/generator/map.go b/internal/generator/map.go similarity index 96% rename from pkg/generator/map.go rename to internal/generator/map.go index 5bc042e..86f25cc 100644 --- a/pkg/generator/map.go +++ b/internal/generator/map.go @@ -5,7 +5,7 @@ import ( "math" "math/rand" - "github.com/iliadenisov/galaxy/pkg/generator/plotter" + "github.com/iliadenisov/galaxy/internal/generator/plotter" ) type Map struct { diff --git a/pkg/generator/map_test.go b/internal/generator/map_test.go similarity index 91% rename from pkg/generator/map_test.go rename to internal/generator/map_test.go index dd8c054..b03b37f 100644 --- a/pkg/generator/map_test.go +++ b/internal/generator/map_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/iliadenisov/galaxy/pkg/number" + "github.com/iliadenisov/galaxy/internal/number" "github.com/stretchr/testify/assert" ) diff --git a/pkg/generator/planet.go b/internal/generator/planet.go similarity index 100% rename from pkg/generator/planet.go rename to internal/generator/planet.go diff --git a/pkg/generator/planet_test.go b/internal/generator/planet_test.go similarity index 93% rename from pkg/generator/planet_test.go rename to internal/generator/planet_test.go index 316cbf8..95b16bc 100644 --- a/pkg/generator/planet_test.go +++ b/internal/generator/planet_test.go @@ -4,7 +4,7 @@ import ( "regexp" "testing" - g "github.com/iliadenisov/galaxy/pkg/generator" + g "github.com/iliadenisov/galaxy/internal/generator" "github.com/stretchr/testify/assert" ) diff --git a/pkg/generator/plotter/plotter.go b/internal/generator/plotter/plotter.go similarity index 97% rename from pkg/generator/plotter/plotter.go rename to internal/generator/plotter/plotter.go index 85a642b..25e5a9b 100644 --- a/pkg/generator/plotter/plotter.go +++ b/internal/generator/plotter/plotter.go @@ -6,7 +6,7 @@ import ( "math" "math/rand" - "github.com/iliadenisov/galaxy/pkg/bitmap" + "github.com/iliadenisov/galaxy/internal/bitmap" ) type Plotter struct { diff --git a/pkg/generator/plotter/plotter_test.go b/internal/generator/plotter/plotter_test.go similarity index 97% rename from pkg/generator/plotter/plotter_test.go rename to internal/generator/plotter/plotter_test.go index 82ee030..3d7ddd2 100644 --- a/pkg/generator/plotter/plotter_test.go +++ b/internal/generator/plotter/plotter_test.go @@ -3,7 +3,7 @@ package plotter_test import ( "testing" - "github.com/iliadenisov/galaxy/pkg/generator/plotter" + "github.com/iliadenisov/galaxy/internal/generator/plotter" ) func TestNewPlotter(t *testing.T) { diff --git a/pkg/generator/settings.go b/internal/generator/settings.go similarity index 100% rename from pkg/generator/settings.go rename to internal/generator/settings.go diff --git a/internal/model/game/fleet.go b/internal/model/game/fleet.go new file mode 100644 index 0000000..c350f52 --- /dev/null +++ b/internal/model/game/fleet.go @@ -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 +} diff --git a/pkg/model/game/game.go b/internal/model/game/game.go similarity index 98% rename from pkg/model/game/game.go rename to internal/model/game/game.go index dae1097..1f8e185 100644 --- a/pkg/model/game/game.go +++ b/internal/model/game/game.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" + e "github.com/iliadenisov/galaxy/internal/error" ) type Game struct { diff --git a/pkg/model/game/game_export_test.go b/internal/model/game/game_export_test.go similarity index 77% rename from pkg/model/game/game_export_test.go rename to internal/model/game/game_export_test.go index 36a67c8..db843e5 100644 --- a/pkg/model/game/game_export_test.go +++ b/internal/model/game/game_export_test.go @@ -6,6 +6,6 @@ func (g *Game) CreateShips(ri int, shipTypeName string, planetNumber int, quanti 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) } diff --git a/pkg/model/game/group.go b/internal/model/game/group.go similarity index 93% rename from pkg/model/game/group.go rename to internal/model/game/group.go index 9234fce..d77a21c 100644 --- a/pkg/model/game/group.go +++ b/internal/model/game/group.go @@ -2,12 +2,13 @@ package game import ( "iter" + "maps" "math" "slices" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" - "github.com/iliadenisov/galaxy/pkg/number" + e "github.com/iliadenisov/galaxy/internal/error" + "github.com/iliadenisov/galaxy/internal/number" ) type CargoType string @@ -120,7 +121,7 @@ func (g *Game) JoinEqualGroups(raceName string) error { } 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) if origin < 2 { return @@ -155,7 +156,7 @@ func (g *Game) createShips(ri int, shipTypeName string, planetNumber int, quanti } var maxIndex uint - for sg := range g.listShipGroups(ri) { + for _, sg := range g.listShipGroups(ri) { if sg.Index > maxIndex { maxIndex = sg.Index } @@ -175,11 +176,11 @@ func (g *Game) createShips(ri int, shipTypeName string, planetNumber int, quanti return nil } -func (g Game) listShipGroups(ri int) iter.Seq[ShipGroup] { - return func(yield func(ShipGroup) bool) { +func (g Game) listShipGroups(ri int) iter.Seq2[int, ShipGroup] { + return func(yield func(int, ShipGroup) bool) { for sg := range g.ShipGroups { if g.ShipGroups[sg].OwnerID == g.Race[ri].ID { - if !yield(g.ShipGroups[sg]) { + if !yield(sg, g.ShipGroups[sg]) { return } } diff --git a/pkg/model/game/group_test.go b/internal/model/game/group_test.go similarity index 84% rename from pkg/model/game/group_test.go rename to internal/model/game/group_test.go index c60c0aa..7b57220 100644 --- a/pkg/model/game/group_test.go +++ b/internal/model/game/group_test.go @@ -1,14 +1,15 @@ package game_test import ( + "iter" "math/rand/v2" "slices" "testing" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" - gg "github.com/iliadenisov/galaxy/pkg/game" - "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/controller" + e "github.com/iliadenisov/galaxy/internal/error" + "github.com/iliadenisov/galaxy/internal/model/game" "github.com/stretchr/testify/assert" ) @@ -296,9 +297,9 @@ func TestJoinEqualGroups(t *testing.T) { Height: 10, 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[1] = gg.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[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] = controller.NewPlanet(1, "Planet_1", g.Race[1].ID, 1, 1, 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) assert.NoError(t, err) @@ -317,48 +318,48 @@ func TestJoinEqualGroups(t *testing.T) { err = g.CreateShips(raceIdx, "R0_Freighter", 0, 1) // 1 -> 2 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) 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) 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) 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) 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 err = g.CreateShips(raceIdx, "R0_Gunship", 0, 9) // 4 -> 6 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 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) 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) 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 err = g.CreateShips(1, "R1_Freighter", 1, 1) 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") assert.NoError(t, err) - assert.Len(t, slices.Collect(g.ListShipGroups(1)), 3) - assert.Len(t, slices.Collect(g.ListShipGroups(raceIdx)), 4) + assert.Len(t, collectGroups(g.ListShipGroups(1)), 3) + assert.Len(t, collectGroups(g.ListShipGroups(raceIdx)), 4) shipTypeID := func(ri int, name string) uuid.UUID { 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 } - for sg := range g.ListShipGroups(raceIdx) { + for _, sg := range g.ListShipGroups(raceIdx) { switch { case sg.TypeID == shipTypeID(raceIdx, "R0_Freighter") && sg.Drive == 1.1: 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 +} diff --git a/pkg/model/game/map.go b/internal/model/game/map.go similarity index 100% rename from pkg/model/game/map.go rename to internal/model/game/map.go diff --git a/pkg/model/game/planet.go b/internal/model/game/planet.go similarity index 98% rename from pkg/model/game/planet.go rename to internal/model/game/planet.go index ae4669c..1e82ee9 100644 --- a/pkg/model/game/planet.go +++ b/internal/model/game/planet.go @@ -5,7 +5,7 @@ import ( "slices" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" + e "github.com/iliadenisov/galaxy/internal/error" ) type UnidentifiedPlanet struct { diff --git a/pkg/model/game/production.go b/internal/model/game/production.go similarity index 98% rename from pkg/model/game/production.go rename to internal/model/game/production.go index 6e4107c..9503059 100644 --- a/pkg/model/game/production.go +++ b/internal/model/game/production.go @@ -4,7 +4,7 @@ import ( "slices" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" + e "github.com/iliadenisov/galaxy/internal/error" ) type PlanetProduction string diff --git a/pkg/model/game/race.go b/internal/model/game/race.go similarity index 100% rename from pkg/model/game/race.go rename to internal/model/game/race.go diff --git a/pkg/model/game/report.go b/internal/model/game/report.go similarity index 100% rename from pkg/model/game/report.go rename to internal/model/game/report.go diff --git a/pkg/model/game/science.go b/internal/model/game/science.go similarity index 98% rename from pkg/model/game/science.go rename to internal/model/game/science.go index 58d1ae9..805df86 100644 --- a/pkg/model/game/science.go +++ b/internal/model/game/science.go @@ -4,7 +4,7 @@ import ( "slices" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" + e "github.com/iliadenisov/galaxy/internal/error" ) type Science struct { @@ -74,6 +74,9 @@ func (g Game) createScienceInternal(ri int, name string, d, w, s, c float64) err if !ok { 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 { 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 { 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{ ID: uuid.New(), ScienceReport: ScienceReport{ diff --git a/pkg/model/game/settings.go b/internal/model/game/settings.go similarity index 100% rename from pkg/model/game/settings.go rename to internal/model/game/settings.go diff --git a/pkg/model/game/ship.go b/internal/model/game/ship.go similarity index 93% rename from pkg/model/game/ship.go rename to internal/model/game/ship.go index fa4acbf..a3f34c4 100644 --- a/pkg/model/game/ship.go +++ b/internal/model/game/ship.go @@ -2,11 +2,10 @@ package game import ( "fmt" - "math" "slices" "github.com/google/uuid" - e "github.com/iliadenisov/galaxy/pkg/error" + e "github.com/iliadenisov/galaxy/internal/error" ) type ShipTypeReport struct { @@ -28,11 +27,6 @@ type ShipTypeReportForeign struct { ShipTypeReport } -type Fleet struct { - OwnerID uuid.UUID `json:"ownerId"` - ShipGroups []ShipGroup `json:"group"` -} - func (st ShipType) Equal(o ShipType) bool { return st.Drive == o.Drive && st.Weapons == o.Weapons && @@ -60,18 +54,6 @@ func (st ShipType) ProductionCost() (mat float64, pop float64) { 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 { for ri := range g.Race { if st := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == id }); st >= 0 { diff --git a/pkg/model/game/ship_test.go b/internal/model/game/ship_test.go similarity index 93% rename from pkg/model/game/ship_test.go rename to internal/model/game/ship_test.go index 1ec4d73..a7d8eec 100644 --- a/pkg/model/game/ship_test.go +++ b/internal/model/game/ship_test.go @@ -3,7 +3,7 @@ package game_test import ( "testing" - "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/model/game" "github.com/stretchr/testify/assert" ) diff --git a/pkg/number/number.go b/internal/number/number.go similarity index 100% rename from pkg/number/number.go rename to internal/number/number.go diff --git a/pkg/number/number_test.go b/internal/number/number_test.go similarity index 100% rename from pkg/number/number_test.go rename to internal/number/number_test.go diff --git a/pkg/repo/fs/fs.go b/internal/repo/fs/fs.go similarity index 100% rename from pkg/repo/fs/fs.go rename to internal/repo/fs/fs.go diff --git a/pkg/repo/fs/fs_test.go b/internal/repo/fs/fs_test.go similarity index 98% rename from pkg/repo/fs/fs_test.go rename to internal/repo/fs/fs_test.go index 152bd03..c5c5256 100644 --- a/pkg/repo/fs/fs_test.go +++ b/internal/repo/fs/fs_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - "github.com/iliadenisov/galaxy/pkg/util" + "github.com/iliadenisov/galaxy/internal/util" "github.com/stretchr/testify/assert" ) diff --git a/pkg/repo/fs/helper_test.go b/internal/repo/fs/helper_test.go similarity index 100% rename from pkg/repo/fs/helper_test.go rename to internal/repo/fs/helper_test.go diff --git a/pkg/repo/fs/util.go b/internal/repo/fs/util.go similarity index 100% rename from pkg/repo/fs/util.go rename to internal/repo/fs/util.go diff --git a/pkg/repo/fs/util_test.go b/internal/repo/fs/util_test.go similarity index 98% rename from pkg/repo/fs/util_test.go rename to internal/repo/fs/util_test.go index 9de9452..5c96b64 100644 --- a/pkg/repo/fs/util_test.go +++ b/internal/repo/fs/util_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/google/uuid" - "github.com/iliadenisov/galaxy/pkg/util" + "github.com/iliadenisov/galaxy/internal/util" "github.com/stretchr/testify/assert" ) diff --git a/pkg/repo/game.go b/internal/repo/game.go similarity index 96% rename from pkg/repo/game.go rename to internal/repo/game.go index c435caf..37273e6 100644 --- a/pkg/repo/game.go +++ b/internal/repo/game.go @@ -11,7 +11,7 @@ package repo import ( "fmt" - "github.com/iliadenisov/galaxy/pkg/model/game" + "github.com/iliadenisov/galaxy/internal/model/game" ) const ( diff --git a/pkg/repo/repo.go b/internal/repo/repo.go similarity index 92% rename from pkg/repo/repo.go rename to internal/repo/repo.go index 3824967..29d9bf5 100644 --- a/pkg/repo/repo.go +++ b/internal/repo/repo.go @@ -4,8 +4,8 @@ import ( "encoding" "errors" - e "github.com/iliadenisov/galaxy/pkg/error" - "github.com/iliadenisov/galaxy/pkg/repo/fs" + e "github.com/iliadenisov/galaxy/internal/error" + "github.com/iliadenisov/galaxy/internal/repo/fs" ) func NewStorageError(err error) error { diff --git a/pkg/util/fs.go b/internal/util/fs.go similarity index 100% rename from pkg/util/fs.go rename to internal/util/fs.go diff --git a/pkg/game/cmd_group.go b/pkg/game/cmd_group.go deleted file mode 100644 index a11372d..0000000 --- a/pkg/game/cmd_group.go +++ /dev/null @@ -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) -} diff --git a/pkg/game/cmd_group_test.go b/pkg/game/cmd_group_test.go deleted file mode 100644 index f2d40f3..0000000 --- a/pkg/game/cmd_group_test.go +++ /dev/null @@ -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) - }) -} diff --git a/pkg/game/cmd_planet.go b/pkg/game/cmd_planet.go deleted file mode 100644 index 3491550..0000000 --- a/pkg/game/cmd_planet.go +++ /dev/null @@ -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) -} diff --git a/pkg/game/cmd_production.go b/pkg/game/cmd_production.go deleted file mode 100644 index 8d9aa0c..0000000 --- a/pkg/game/cmd_production.go +++ /dev/null @@ -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) -} diff --git a/pkg/game/cmd_science.go b/pkg/game/cmd_science.go deleted file mode 100644 index 70040e3..0000000 --- a/pkg/game/cmd_science.go +++ /dev/null @@ -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) -} diff --git a/pkg/game/cmd_ship_type.go b/pkg/game/cmd_ship_type.go deleted file mode 100644 index d2f6fe3..0000000 --- a/pkg/game/cmd_ship_type.go +++ /dev/null @@ -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) -} diff --git a/pkg/game/cmd_war_peace.go b/pkg/game/cmd_war_peace.go deleted file mode 100644 index 91a7b73..0000000 --- a/pkg/game/cmd_war_peace.go +++ /dev/null @@ -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) -} diff --git a/pkg/game/controller.go b/pkg/game/controller.go deleted file mode 100644 index d56dfcd..0000000 --- a/pkg/game/controller.go +++ /dev/null @@ -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() -} diff --git a/pkg/game/game.go b/pkg/game/game.go deleted file mode 100644 index 954d423..0000000 --- a/pkg/game/game.go +++ /dev/null @@ -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) -} diff --git a/pkg/model/command/command.go b/pkg/model/command/command.go deleted file mode 100644 index 820a173..0000000 --- a/pkg/model/command/command.go +++ /dev/null @@ -1,15 +0,0 @@ -package command - -type Command struct { - FromRace string -} - -type CommandAlly struct { - Command - ToRace string -} - -type CommandWar struct { - Command - ToRace string -}