package repo /* /state.json /0001/state.json /0001/meta.json /0001/bombing.json /0001/battle/{UUID}.json /0001/report/{UUID}.json */ import ( "fmt" "github.com/google/uuid" "github.com/iliadenisov/galaxy/internal/model/game" "github.com/iliadenisov/galaxy/internal/model/report" ) const ( statePath = "state.json" metaPath = "meta.json" ) func (r *repo) SaveReport(t uint, rep *report.Report) error { return saveReport(r.s, t, rep) } func saveReport(s Storage, t uint, v *report.Report) error { path := repDir(t, v.RaceID) if err := s.Write(path, v); err != nil { return NewStorageError(err) } return nil } func (r *repo) LoadReport(t uint, id uuid.UUID) (*report.Report, error) { return loadReport(r.s, t, id) } func loadReport(s Storage, t uint, id uuid.UUID) (*report.Report, error) { path := repDir(t, id) result := new(report.Report) exist, err := s.Exists(path) if err != nil { return nil, NewStorageError(err) } if !exist { return nil, NewReportNotFoundError() } if err := s.ReadSafe(path, result); err != nil { return nil, NewStorageError(err) } return result, nil } func (r *repo) SaveNewTurn(t uint, g *game.Game) error { return saveNewTurn(r.s, t, g) } func saveNewTurn(s Storage, t uint, g *game.Game) error { path := fmt.Sprintf("%s/state.json", turnDir(t)) exist, err := s.Exists(path) if err != nil { return NewStorageError(err) } if exist { return NewStateError(fmt.Sprintf("turn %d already saved at %s", t, path)) } if err := s.Write(path, g); err != nil { return NewStorageError(err) } return saveLastState(s, g) } func (r *repo) SaveLastState(g *game.Game) error { return saveLastState(r.s, g) } func saveLastState(s Storage, g *game.Game) error { if err := s.Write(statePath, g); err != nil { return NewStorageError(err) } return nil } func (r *repo) LoadState() (*game.Game, error) { return loadState(r.s, true) } func (r *repo) LoadStateSafe() (*game.Game, error) { return loadState(r.s, false) } func loadState(s Storage, locked bool) (*game.Game, error) { var result *game.Game = new(game.Game) path := statePath exist, err := s.Exists(path) if err != nil { return nil, NewStorageError(err) } if !exist { return nil, NewGameNotInitializedError() } if locked { if err := s.Read(path, result); err != nil { return nil, NewStorageError(err) } } else { if err := s.ReadSafe(path, result); err != nil { return nil, NewStorageError(err) } } return result, nil } func loadMeta(s Storage) (*game.GameMeta, error) { var result *game.GameMeta = new(game.GameMeta) path := metaPath exist, err := s.Exists(path) if err != nil { return nil, NewStorageError(err) } if !exist { return result, nil } if err := s.ReadSafe(path, result); err != nil { return nil, NewStorageError(err) } return result, nil } func saveMeta(s Storage, t uint, gm *game.GameMeta) error { // save turn's meta path := fmt.Sprintf("%s/%s", turnDir(t), metaPath) if err := s.Write(path, gm); err != nil { return NewStorageError(err) } // also save as latest meta path = metaPath if err := s.Write(path, gm); err != nil { return NewStorageError(err) } return nil } func (r *repo) SaveBattle(t uint, b *report.BattleReport, m *game.BattleMeta) error { meta, err := loadMeta(r.s) if err != nil { return err } err = saveBattle(r.s, t, b) if err != nil { return err } meta.Battles = append(meta.Battles, *m) return saveMeta(r.s, t, meta) } func saveBattle(s Storage, t uint, b *report.BattleReport) error { path := fmt.Sprintf("%s/battle/%s.json", turnDir(t), b.ID.String()) exist, err := s.Exists(path) if err != nil { return NewStorageError(err) } if exist { return NewStateError(fmt.Sprintf("battle %v for turn %d already has been saved", b.ID, t)) } if err := s.Write(path, b); err != nil { return NewStorageError(err) } return nil } func (r *repo) SaveBombings(t uint, b []*game.Bombing) error { meta, err := loadMeta(r.s) if err != nil { return err } for i := range b { meta.Bombings = append(meta.Bombings, *b[i]) } return saveMeta(r.s, t, meta) } func repDir(t uint, id uuid.UUID) string { return fmt.Sprintf("%s/report/%s.json", turnDir(t), id.String()) } func turnDir(t uint) string { return fmt.Sprintf("%04d", t) }