108 lines
2.4 KiB
Go
108 lines
2.4 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
|
"github.com/iliadenisov/galaxy/internal/model/report"
|
|
"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
|
|
SaveNewTurn(uint, *game.Game) error
|
|
|
|
// SaveState stores current game state updated between turns
|
|
SaveLastState(*game.Game) error
|
|
|
|
// LoadState retrieves game current state with required lock acquisition
|
|
LoadState() (*game.Game, error)
|
|
|
|
// LoadStateSafe retrieves game current state without preliminary locking
|
|
LoadStateSafe() (*game.Game, error)
|
|
|
|
// SaveBattle stores a new battle protocol and battle meta data for turn t
|
|
SaveBattle(uint, *report.BattleReport, *game.BattleMeta) error
|
|
|
|
// SaveBombing stores all prodused bombings for turn t
|
|
SaveBombings(uint, []*game.Bombing) error
|
|
|
|
// SaveReport stores latest report for a race
|
|
SaveReport(uint, *report.Report) error
|
|
|
|
// LoadReport loads report for specific turn and player id
|
|
LoadReport(uint, uuid.UUID) (*report.Report, error)
|
|
}
|
|
|
|
type Controller struct {
|
|
Repo Repo
|
|
Cache *Cache
|
|
}
|
|
|
|
type Param struct {
|
|
StoragePath string
|
|
}
|
|
|
|
type Configurer func(*Param)
|
|
|
|
func NewController(config Configurer) (*Controller, error) {
|
|
c := &Param{
|
|
StoragePath: ".",
|
|
}
|
|
if config != nil {
|
|
config(c)
|
|
}
|
|
r, err := repo.NewFileRepo(c.StoragePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Controller{
|
|
Repo: r,
|
|
}, nil
|
|
}
|
|
|
|
func NewRepoController(r Repo) *Controller {
|
|
return &Controller{
|
|
Repo: r,
|
|
}
|
|
}
|
|
|
|
func (c *Controller) ExecuteState(consumer func(Repo) error) (err error) {
|
|
if err := c.Repo.Lock(); err != nil {
|
|
return fmt.Errorf("execute: lock failed: %s", err)
|
|
}
|
|
defer func() {
|
|
err = errors.Join(err, c.Repo.Release())
|
|
}()
|
|
err = consumer(c.Repo)
|
|
return
|
|
}
|
|
|
|
func (c *Controller) ExecuteCommand(consumer func(Repo, *game.Game) error) (err 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
|
|
}
|
|
defer func() {
|
|
err = errors.Join(err, c.Repo.Release())
|
|
}()
|
|
c.Cache = NewCache(g)
|
|
err = consumer(c.Repo, g)
|
|
if err == nil {
|
|
g.Stage += 1
|
|
c.Repo.SaveLastState(g)
|
|
}
|
|
return
|
|
}
|