package db import ( "context" "database/sql" "github.com/ryanhamamura/c4/db/gen" "github.com/ryanhamamura/c4/game" ) type GamePersister struct { queries *gen.Queries } func NewGamePersister(q *gen.Queries) *GamePersister { return &GamePersister{queries: q} } func (p *GamePersister) SaveGame(g *game.Game) error { ctx := context.Background() existing, err := p.queries.GetGame(ctx, g.ID) if err == sql.ErrNoRows { _, err = p.queries.CreateGame(ctx, gen.CreateGameParams{ ID: g.ID, Board: g.BoardToJSON(), CurrentTurn: int64(g.CurrentTurn), Status: int64(g.Status), }) return err } if err != nil { return err } var winnerUserID sql.NullString if g.Winner != nil && g.Winner.UserID != nil { winnerUserID = sql.NullString{String: *g.Winner.UserID, Valid: true} } winningCells := sql.NullString{} if wc := g.WinningCellsToJSON(); wc != "" { winningCells = sql.NullString{String: wc, Valid: true} } _ = existing return p.queries.UpdateGame(ctx, gen.UpdateGameParams{ Board: g.BoardToJSON(), CurrentTurn: int64(g.CurrentTurn), Status: int64(g.Status), WinnerUserID: winnerUserID, WinningCells: winningCells, ID: g.ID, }) } func (p *GamePersister) LoadGame(id string) (*game.Game, error) { ctx := context.Background() row, err := p.queries.GetGame(ctx, id) if err != nil { return nil, err } g := &game.Game{ ID: row.ID, CurrentTurn: int(row.CurrentTurn), Status: game.GameStatus(row.Status), } if err := g.BoardFromJSON(row.Board); err != nil { return nil, err } if row.WinningCells.Valid { g.WinningCellsFromJSON(row.WinningCells.String) } return g, nil } func (p *GamePersister) SaveGamePlayer(gameID string, player *game.Player, slot int) error { ctx := context.Background() var userID, guestPlayerID sql.NullString if player.UserID != nil { userID = sql.NullString{String: *player.UserID, Valid: true} } else { guestPlayerID = sql.NullString{String: string(player.ID), Valid: true} } return p.queries.CreateGamePlayer(ctx, gen.CreateGamePlayerParams{ GameID: gameID, UserID: userID, GuestPlayerID: guestPlayerID, Nickname: player.Nickname, Color: int64(player.Color), Slot: int64(slot), }) } func (p *GamePersister) LoadGamePlayers(gameID string) ([]*game.Player, error) { ctx := context.Background() rows, err := p.queries.GetGamePlayers(ctx, gameID) if err != nil { return nil, err } players := make([]*game.Player, 0, len(rows)) for _, row := range rows { player := &game.Player{ Nickname: row.Nickname, Color: int(row.Color), } if row.UserID.Valid { player.UserID = &row.UserID.String player.ID = game.PlayerID(row.UserID.String) } else if row.GuestPlayerID.Valid { player.ID = game.PlayerID(row.GuestPlayerID.String) } players = append(players, player) } return players, nil }