craban/server/services/store/game.go
2021-09-13 21:58:52 +02:00

157 lines
3.2 KiB
Go

package store
import (
"database/sql"
"fmt"
sq "github.com/Masterminds/squirrel"
"git.ctrlz.es/mgdelacroix/craban/model"
)
var gameColumns = []string{"id", "user_id", "name"}
var gameMemberColumns = []string{"game_id", "user_id", "role"}
type GameStore struct {
Conn *sql.DB
}
func NewGameStore(s *Store) *GameStore {
return &GameStore{Conn: s.Conn}
}
func (gs *GameStore) Q() sq.StatementBuilderType {
return sq.StatementBuilder.RunWith(gs.Conn)
}
func (gs *GameStore) gamesFromRows(rows *sql.Rows) ([]*model.Game, error) {
games := []*model.Game{}
for rows.Next() {
var game model.Game
err := rows.Scan(
&game.ID,
&game.UserID,
&game.Name,
)
if err != nil {
return nil, err
}
games = append(games, &game)
}
return games, nil
}
func (gs *GameStore) getGameByCondition(condition sq.Eq) (*model.Game, error) {
games, err := gs.getGamesByCondition(condition)
if err != nil {
return nil, err
}
return games[0], nil
}
func (gs *GameStore) getGamesByCondition(condition sq.Eq) ([]*model.Game, error) {
rows, err := gs.Q().Select(gameColumns...).
From("games").
Where(condition).
Query()
if err != nil {
return nil, fmt.Errorf("cannot get games: %w", err)
}
defer rows.Close()
games, err := gs.gamesFromRows(rows)
if err != nil {
return nil, fmt.Errorf("cannot get games from rows: %w", err)
}
if len(games) == 0 {
return nil, sql.ErrNoRows
}
return games, nil
}
func (gs *GameStore) GetByID(id int) (*model.Game, error) {
return gs.getGameByCondition(sq.Eq{"id": id})
}
func (gs *GameStore) Create(name string, userID int) (*model.Game, error) {
// ToDo: generate transaction
// ToDo: add tests
res, err := gs.Q().Insert("games").
Columns(gameColumns[1:]...).
Values(userID, name).
Exec()
if err != nil {
return nil, fmt.Errorf("cannot insert game: %w", err)
}
id, err := res.LastInsertId()
if err != nil {
return nil, fmt.Errorf("cannot get last insert id for created game: %w", err)
}
game, err := gs.GetByID(int(id))
if err != nil {
return nil, fmt.Errorf("cannot get game by id: %w", err)
}
res, err = gs.Q().Insert("gamemembers").
Columns(gameMemberColumns...).
Values(game.ID, userID, model.RoleGameMaster).
Exec()
if err != nil {
return nil, fmt.Errorf("cannot insert gamemember for created game: %w", err)
}
return game, nil
}
func (gs *GameStore) gameMembersFromRows(rows *sql.Rows) ([]*model.GameMember, error) {
gameMembers := []*model.GameMember{}
for rows.Next() {
var gameMember model.GameMember
err := rows.Scan(
&gameMember.GameID,
&gameMember.UserID,
&gameMember.Role,
)
if err != nil {
return nil, err
}
gameMembers = append(gameMembers, &gameMember)
}
return gameMembers, nil
}
func (gs *GameStore) GetGameMembers(gameID int) ([]*model.GameMember, error) {
rows, err := gs.Q().Select(gameMemberColumns...).
From("gamemembers").
Where(sq.Eq{"game_id": gameID}).
Query()
if err != nil {
return nil, fmt.Errorf("cannot get gamemembers: %w", err)
}
defer rows.Close()
gameMembers, err := gs.gameMembersFromRows(rows)
if err != nil {
return nil, fmt.Errorf("cannot get game members from rows: %w", err)
}
if len(gameMembers) == 0 {
return nil, sql.ErrNoRows
}
return gameMembers, nil
}