Feat: room and actions repos

This commit is contained in:
Grail Finder
2025-07-01 12:49:46 +03:00
parent 42348ff625
commit 83d3a19d05
6 changed files with 171 additions and 50 deletions

10
go.mod
View File

@ -4,5 +4,15 @@ go 1.24
require (
github.com/BurntSushi/toml v1.5.0
github.com/jackc/pgx/v5 v5.7.5
github.com/rs/xid v1.6.0
)
require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/text v0.24.0 // indirect
)

28
go.sum
View File

@ -1,4 +1,32 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -70,33 +70,33 @@ type CardMark struct {
type Room struct {
ID string `json:"id" db:"id"`
CreatedAt time.Time `json:"created_at" db:"created_at"` // limit?
RoomLink string
CreatorName string `json:"creator_name"`
ActionHistory []Action
TeamTurn UserTeam
RedTeam Team
BlueTeam Team
Cards []WordCard
ThisTurnLimit uint8 // how many cards guessers can open this turn
OpenedThisTurn uint8 // how many cards have been opened this turn
WCMap map[string]WordColor
BotMap map[string]BotPlayer // key is bot name
BlueCounter uint8
RedCounter uint8
RedTurn bool // false is blue turn
MimeDone bool
IsPublic bool
IsRunning bool `json:"is_running"`
Language string `json:"language" example:"en" form:"language"`
RoundTime int32 `json:"round_time"`
IsOver bool
TeamWon UserTeam // blue | red
//
Mark CardMark // card is marked
// needed for debug
LogJournal []string
Settings GameSettings
CreatedAt time.Time `json:"created_at" db:"created_at"`
CreatorName string `json:"creator_name" db:"creator_name"`
TeamTurn UserTeam `db:"team_turn"`
ThisTurnLimit uint8 `db:"this_turn_limit"`
OpenedThisTurn uint8 `db:"opened_this_turn"`
BlueCounter uint8 `db:"blue_counter"`
RedCounter uint8 `db:"red_counter"`
RedTurn bool `db:"red_turn"`
MimeDone bool `db:"mime_done"`
IsPublic bool `db:"is_public"`
IsRunning bool `json:"is_running" db:"is_running"`
Language string `json:"language" example:"en" form:"language" db:"language"`
RoundTime uint32 `json:"round_time" db:"round_time"`
IsOver bool `db:"is_over"`
TeamWon UserTeam `db:"team_won"`
RoomPass string `json:"room_pass" db:"room_pass"`
// fields not in db
RoomLink string `db:"-"`
ActionHistory []Action `db:"-"`
RedTeam Team `db:"-"`
BlueTeam Team `db:"-"`
Cards []WordCard `db:"-"`
WCMap map[string]WordColor `db:"-"`
BotMap map[string]BotPlayer `db:"-"`
Mark CardMark `db:"-"`
LogJournal []string `db:"-"`
Settings GameSettings `db:"-"`
}
func (r *Room) ClearMarks() {
@ -325,10 +325,10 @@ type WordCard struct {
}
type GameSettings struct {
Language string `json:"language" example:"en" form:"language"`
RoomPass string `json:"room_pass"`
TurnSecondsLeft uint32
RoundTime uint32
Language string `json:"language" example:"en" form:"language" db:"language"`
RoomPass string `json:"room_pass" db:"room_pass"`
TurnSecondsLeft uint32 `db:"-"`
RoundTime uint32 `json:"round_time" db:"round_time"`
}
// =====
@ -343,19 +343,14 @@ type RoomReq struct {
func (rr *RoomReq) CreateRoom(creator string) *Room {
roomID := xid.New().String()
settings := GameSettings{
Language: rr.Language,
RoomPass: rr.RoomPass,
RoundTime: rr.RoundTime,
}
return &Room{
// RoomName: ,
ID: roomID,
CreatedAt: time.Now(),
// PlayerList: []string{creator},
CreatorName: creator,
Language: rr.Language,
RoundTime: rr.RoundTime,
RoomPass: rr.RoomPass,
BotMap: make(map[string]BotPlayer),
Settings: settings,
}
}

46
repos/actions.go Normal file
View File

@ -0,0 +1,46 @@
package repos
import (
"context"
"gralias/models"
"github.com/jackc/pgx/v5"
)
type ActionsRepo interface {
ListActions(ctx context.Context, roomID string) ([]models.Action, error)
CreateAction(ctx context.Context, roomID string, action *models.Action) error
GetLastClue(ctx context.Context, roomID string) (*models.Action, error)
DeleteActionsByRoomID(ctx context.Context, roomID string) error
}
func (p *RepoProvider) ListActions(ctx context.Context, roomID string) ([]models.Action, error) {
rows, err := p.DB.Query(ctx, `SELECT actor, actor_color, action_type, word, word_color, number_associated FROM actions WHERE room_id = $1 ORDER BY created_at ASC`, roomID)
if err != nil {
return nil, err
}
return pgx.CollectRows(rows, pgx.RowToStructByName[models.Action])
}
func (p *RepoProvider) CreateAction(ctx context.Context, roomID string, a *models.Action) error {
_, err := p.DB.Exec(ctx, `INSERT INTO actions (room_id, actor, actor_color, action_type, word, word_color, number_associated) VALUES ($1, $2, $3, $4, $5, $6, $7)`,
roomID, a.Actor, a.ActorColor, a.Action, a.Word, a.WordColor, a.Number)
return err
}
func (p *RepoProvider) GetLastClue(ctx context.Context, roomID string) (*models.Action, error) {
rows, err := p.DB.Query(ctx, `SELECT actor, actor_color, action_type, word, word_color, number_associated FROM actions WHERE room_id = $1 AND action_type = 'gave_clue' ORDER BY created_at DESC LIMIT 1`, roomID)
if err != nil {
return nil, err
}
action, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[models.Action])
if err != nil {
return nil, err
}
return &action, nil
}
func (p *RepoProvider) DeleteActionsByRoomID(ctx context.Context, roomID string) error {
_, err := p.DB.Exec(ctx, `DELETE FROM actions WHERE room_id = $1`, roomID)
return err
}

View File

@ -1,9 +1,11 @@
package repos
import "github.com/jackc/pgx/v5/pgxpool"
type AllRepos interface {
RoomsRepo
}
type RepoProvider struct {
// db connection
DB *pgxpool.Pool
}

View File

@ -1,15 +1,55 @@
package repos
import "gralias/models"
import (
"context"
"gralias/models"
"github.com/jackc/pgx/v5"
)
type RoomsRepo interface {
ListRooms() ([]models.Room, error)
GetRoomByID(id string) (*models.Room, error)
CreateRoom(room *models.Room) error
DeleteRoomByID(id string) error
ListRooms(ctx context.Context) ([]models.Room, error)
GetRoomByID(ctx context.Context, id string) (*models.Room, error)
CreateRoom(ctx context.Context, room *models.Room) error
DeleteRoomByID(ctx context.Context, id string) error
UpdateRoom(ctx context.Context, room *models.Room) error
}
// provider implementation
func (p RepoProvider) ListRooms() ([]models.Room, error) {
return nil, nil
func (p *RepoProvider) ListRooms(ctx context.Context) ([]models.Room, error) {
rows, err := p.DB.Query(ctx, `SELECT * FROM rooms`)
if err != nil {
return nil, err
}
rooms, err := pgx.CollectRows(rows, pgx.RowToStructByName[models.Room])
if err != nil {
return nil, err
}
return rooms, nil
}
func (p *RepoProvider) GetRoomByID(ctx context.Context, id string) (*models.Room, error) {
rows, err := p.DB.Query(ctx, `SELECT * FROM rooms WHERE id = $1`, id)
if err != nil {
return nil, err
}
room, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[models.Room])
if err != nil {
return nil, err
}
return &room, nil
}
func (p *RepoProvider) CreateRoom(ctx context.Context, r *models.Room) error {
_, err := p.DB.Exec(ctx, `INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_public, is_running, language, round_time, is_over, team_won, room_pass) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)`, r.ID, r.CreatedAt, r.CreatorName, r.TeamTurn, r.ThisTurnLimit, r.OpenedThisTurn, r.BlueCounter, r.RedCounter, r.RedTurn, r.MimeDone, r.IsPublic, r.IsRunning, r.Language, r.RoundTime, r.IsOver, r.TeamWon, r.Settings.RoomPass)
return err
}
func (p *RepoProvider) DeleteRoomByID(ctx context.Context, id string) error {
_, err := p.DB.Exec(ctx, `DELETE FROM rooms WHERE id = $1`, id)
return err
}
func (p *RepoProvider) UpdateRoom(ctx context.Context, r *models.Room) error {
_, err := p.DB.Exec(ctx, `UPDATE rooms SET team_turn = $1, this_turn_limit = $2, opened_this_turn = $3, blue_counter = $4, red_counter = $5, red_turn = $6, mime_done = $7, is_public = $8, is_running = $9, language = $10, round_time = $11, is_over = $12, team_won = $13, room_pass = $14 WHERE id = $15`, r.TeamTurn, r.ThisTurnLimit, r.OpenedThisTurn, r.BlueCounter, r.RedCounter, r.RedTurn, r.MimeDone, r.IsPublic, r.IsRunning, r.Language, r.RoundTime, r.IsOver, r.TeamWon, r.Settings.RoomPass, r.ID)
return err
}