commands A, W

This commit is contained in:
Ilia Denisov
2025-09-30 20:44:10 +03:00
parent 128d6862a7
commit 04fc96dc8f
6 changed files with 179 additions and 51 deletions
+8 -16
View File
@@ -3,29 +3,21 @@ 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) { err = updateRelation(r, from, to, game.RelationWar) }) })
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) { err = updateRelation(r, from, to, game.RelationPeace) }) })
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, hostRace, opponentRace string, rel game.Relation) error {
g, err := r.LoadState()
if err != nil {
return err
}
hostID, err := g.HostRaceID(hostRace)
if err != nil {
return err
}
opponentID, err := g.OpponentRaceID(opponentRace)
if err != nil {
return err
}
if err := g.UpdateRelation(hostID, opponentID, rel); err != nil {
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)
+59 -15
View File
@@ -1,26 +1,70 @@
package game_test
import (
"fmt"
"testing"
"github.com/iliadenisov/galaxy/pkg/game"
"github.com/iliadenisov/galaxy/pkg/util"
mg "github.com/iliadenisov/galaxy/pkg/model/game"
"github.com/stretchr/testify/assert"
)
func TestRelation(t *testing.T) {
root, cleanup := util.CreateWorkDir(t)
defer cleanup()
players := 20
races := make([]string, players)
for i := range players {
races[i] = fmt.Sprintf("race_%02d", i)
}
_, err := game.ComposeGame(func(p *game.Param) { p.StoragePath = root }, races)
assert.NoError(t, err)
func TestDeclarePeaceAndWarSingle(t *testing.T) {
g(t, func(f func(*game.Param), g func() mg.Game) {
hostRace := "race_05"
opponentRace := "race_01"
err = game.DeclarePeace(func(p *game.Param) { p.StoragePath = root }, "race_05", "race_01")
assert.NoError(t, err)
// TODO: check relation state changed
r, err := g().Relation(hostRace, opponentRace)
assert.NoError(t, err)
assert.Equal(t, mg.RelationWar, r.Relation)
assert.NoError(t, game.DeclarePeace(f, hostRace, opponentRace))
r, err = g().Relation(hostRace, opponentRace)
assert.NoError(t, err)
assert.Equal(t, mg.RelationPeace, r.Relation)
assert.NoError(t, game.DeclareWar(f, hostRace, opponentRace))
r, err = g().Relation(hostRace, opponentRace)
assert.NoError(t, err)
assert.Equal(t, mg.RelationWar, r.Relation)
})
}
func TestDeclarePeaceAndWarAll(t *testing.T) {
g(t, func(f func(*game.Param), g func() mg.Game) {
hostRace := "race_07"
for i := range testRaceCount {
opponentRace := raceNum(i)
if opponentRace == hostRace {
continue
}
r, err := g().Relation(hostRace, opponentRace)
assert.NoError(t, err)
assert.Equal(t, mg.RelationWar, r.Relation)
}
assert.NoError(t, game.DeclarePeace(f, hostRace, hostRace))
for i := range testRaceCount {
opponentRace := raceNum(i)
if opponentRace == hostRace {
continue
}
r, err := g().Relation(hostRace, opponentRace)
assert.NoError(t, err)
assert.Equal(t, mg.RelationPeace, r.Relation)
}
assert.NoError(t, game.DeclareWar(f, hostRace, hostRace))
for i := range testRaceCount {
opponentRace := raceNum(i)
if opponentRace == hostRace {
continue
}
r, err := g().Relation(hostRace, opponentRace)
assert.NoError(t, err)
assert.Equal(t, mg.RelationWar, r.Relation)
}
})
}
+21 -3
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/google/uuid"
"github.com/iliadenisov/galaxy/pkg/model/game"
"github.com/iliadenisov/galaxy/pkg/repo"
)
@@ -16,8 +17,13 @@ type Param struct {
StoragePath string
}
func ComposeGame(configure func(*Param), races []string) (gameID uuid.UUID, err error) {
control(configure, func(c *ctrl) { c.execute(func(r Repo) { gameID, err = newGame(r, races) }) })
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
}
@@ -47,10 +53,22 @@ func control(configure func(*Param), consumer func(*ctrl)) error {
return nil
}
func (c *ctrl) execute(consumer func(Repo)) error {
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()
}
+35 -9
View File
@@ -5,21 +5,47 @@ import (
"testing"
"github.com/iliadenisov/galaxy/pkg/game"
mg "github.com/iliadenisov/galaxy/pkg/model/game"
"github.com/iliadenisov/galaxy/pkg/util"
"github.com/stretchr/testify/assert"
)
const (
testRaceCount = 20
)
func raceNum(i int) string {
return fmt.Sprintf("race_%02d", i)
}
func TestComposeGame(t *testing.T) {
g(t, func(p func(*game.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(func(*game.Param), func() mg.Game)) {
root, cleanup := util.CreateWorkDir(t)
defer cleanup()
players := 20
races := make([]string, players)
for i := range players {
races[i] = fmt.Sprintf("race_%02d", i)
races := make([]string, testRaceCount)
for i := range testRaceCount {
races[i] = raceNum(i)
}
_, err := game.ComposeGame(func(p *game.Param) { p.StoragePath = root }, races)
assert.NoError(t, err)
_, err = game.ComposeGame(func(p *game.Param) { p.StoragePath = root }, races)
assert.Error(t, err)
assert.ErrorContains(t, err, "state for turn 0 already saved")
p := func(p *game.Param) { p.StoragePath = root }
_, err := game.GenerateGame(p, races)
if err != nil {
assert.FailNow(t, "g: ComposeGame", err)
return
}
g := func() mg.Game {
g, err := game.LoadState(p)
if err != nil {
assert.FailNow(t, "g: LoadState", err)
return mg.Game{}
}
return g
}
f(p, g)
}