generated from VLADIMIR/template
up
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
// Package game_screen_plans_repo persists game screen plans.
|
||||
package game_screen_plans_repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
var ErrPlanNotFound = errors.New("план экранов не найден")
|
||||
|
||||
// Step is a stored screen plan step.
|
||||
type Step struct {
|
||||
Mode int32 `json:"mode"`
|
||||
Text string `json:"text,omitempty"`
|
||||
TimerLabel string `json:"timerLabel,omitempty"`
|
||||
TimerDurationSeconds int64 `json:"timerDurationSeconds,omitempty"`
|
||||
}
|
||||
|
||||
// Plan is a stored game screen plan.
|
||||
type Plan struct {
|
||||
GameID int
|
||||
Steps []Step
|
||||
CurrentStep int
|
||||
}
|
||||
|
||||
// GameScreenPlansRepo persists game screen plans.
|
||||
type GameScreenPlansRepo struct {
|
||||
pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
// NewGameScreenPlansRepo creates a game screen plans repository.
|
||||
func NewGameScreenPlansRepo(pool *pgxpool.Pool) *GameScreenPlansRepo {
|
||||
return &GameScreenPlansRepo{pool: pool}
|
||||
}
|
||||
|
||||
func (r *GameScreenPlansRepo) Get(ctx context.Context, gameID int) (*Plan, error) {
|
||||
plan := &Plan{GameID: gameID}
|
||||
var raw []byte
|
||||
err := r.pool.QueryRow(
|
||||
ctx,
|
||||
`
|
||||
SELECT steps, current_step
|
||||
FROM game_screen_plans
|
||||
WHERE game_id = $1`,
|
||||
gameID,
|
||||
).Scan(&raw, &plan.CurrentStep)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrPlanNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(raw, &plan.Steps); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plan, nil
|
||||
}
|
||||
|
||||
func (r *GameScreenPlansRepo) Save(ctx context.Context, gameID int, steps []Step, currentStep int) (*Plan, error) {
|
||||
raw, err := json.Marshal(steps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.pool.Exec(
|
||||
ctx,
|
||||
`
|
||||
INSERT INTO game_screen_plans (game_id, steps, current_step)
|
||||
VALUES ($1, $2::jsonb, $3)
|
||||
ON CONFLICT (game_id) DO UPDATE SET
|
||||
steps = EXCLUDED.steps,
|
||||
current_step = EXCLUDED.current_step,
|
||||
updated_at = NOW()`,
|
||||
gameID,
|
||||
raw,
|
||||
currentStep,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Plan{GameID: gameID, Steps: steps, CurrentStep: currentStep}, nil
|
||||
}
|
||||
|
||||
func (r *GameScreenPlansRepo) Delete(ctx context.Context, gameID int) error {
|
||||
_, err := r.pool.Exec(
|
||||
ctx,
|
||||
`DELETE FROM game_screen_plans
|
||||
WHERE game_id = $1`,
|
||||
gameID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -29,6 +29,7 @@ type ScreenSession struct {
|
||||
TimerRemainingSeconds int64
|
||||
TimerState int32
|
||||
TimerEndsAt *time.Time
|
||||
Text string
|
||||
}
|
||||
|
||||
// ScreenSessionsRepo persists screen sessions.
|
||||
@@ -56,11 +57,11 @@ func (r *ScreenSessionsRepo) Get(ctx context.Context, id int, tokenHash string)
|
||||
session := &ScreenSession{ID: id}
|
||||
err := r.pool.QueryRow(ctx, `
|
||||
SELECT game_id, sound_enabled, last_seen_at, mode, state_version, position_ms, command, volume,
|
||||
timer_label, timer_duration_seconds, timer_remaining_seconds, timer_state, timer_ends_at
|
||||
timer_label, timer_duration_seconds, timer_remaining_seconds, timer_state, timer_ends_at, text
|
||||
FROM screen_sessions
|
||||
WHERE id = $1 AND access_token_hash = $2`, id, tokenHash).
|
||||
Scan(&session.GameID, &session.Sound, &session.LastSeen, &session.Mode, &session.Version, &session.Position, &session.Command, &session.Volume,
|
||||
&session.TimerLabel, &session.TimerDurationSeconds, &session.TimerRemainingSeconds, &session.TimerState, &session.TimerEndsAt)
|
||||
&session.TimerLabel, &session.TimerDurationSeconds, &session.TimerRemainingSeconds, &session.TimerState, &session.TimerEndsAt, &session.Text)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrScreenNotFound
|
||||
}
|
||||
@@ -79,7 +80,7 @@ func (r *ScreenSessionsRepo) Get(ctx context.Context, id int, tokenHash string)
|
||||
func (r *ScreenSessionsRepo) ListByGame(ctx context.Context, gameID int) ([]*ScreenSession, error) {
|
||||
rows, err := r.pool.Query(ctx, `
|
||||
SELECT id, game_id, sound_enabled, last_seen_at, mode, state_version, position_ms, command, volume,
|
||||
timer_label, timer_duration_seconds, timer_remaining_seconds, timer_state, timer_ends_at
|
||||
timer_label, timer_duration_seconds, timer_remaining_seconds, timer_state, timer_ends_at, text
|
||||
FROM screen_sessions
|
||||
WHERE game_id = $1
|
||||
ORDER BY id`, gameID)
|
||||
@@ -92,7 +93,7 @@ func (r *ScreenSessionsRepo) ListByGame(ctx context.Context, gameID int) ([]*Scr
|
||||
for rows.Next() {
|
||||
session := &ScreenSession{}
|
||||
if err := rows.Scan(&session.ID, &session.GameID, &session.Sound, &session.LastSeen, &session.Mode, &session.Version, &session.Position, &session.Command, &session.Volume,
|
||||
&session.TimerLabel, &session.TimerDurationSeconds, &session.TimerRemainingSeconds, &session.TimerState, &session.TimerEndsAt); err != nil {
|
||||
&session.TimerLabel, &session.TimerDurationSeconds, &session.TimerRemainingSeconds, &session.TimerState, &session.TimerEndsAt, &session.Text); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessions = append(sessions, session)
|
||||
@@ -102,7 +103,35 @@ func (r *ScreenSessionsRepo) ListByGame(ctx context.Context, gameID int) ([]*Scr
|
||||
|
||||
// SetMode updates the display mode for a game.
|
||||
func (r *ScreenSessionsRepo) SetMode(ctx context.Context, gameID int, mode int32) error {
|
||||
_, err := r.pool.Exec(ctx, `UPDATE screen_sessions SET mode = $2, command = 0, state_version = state_version + 1, updated_at = NOW() WHERE game_id = $1`, gameID, mode)
|
||||
_, err := r.pool.Exec(
|
||||
ctx,
|
||||
`UPDATE screen_sessions
|
||||
SET mode = $2,
|
||||
text = '',
|
||||
command = 0,
|
||||
state_version = state_version + 1,
|
||||
updated_at = NOW()
|
||||
WHERE game_id = $1`,
|
||||
gameID,
|
||||
mode,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetText updates the text screen for a game.
|
||||
func (r *ScreenSessionsRepo) SetText(ctx context.Context, gameID int, text string) error {
|
||||
_, err := r.pool.Exec(
|
||||
ctx,
|
||||
`UPDATE screen_sessions
|
||||
SET mode = 8,
|
||||
text = $2,
|
||||
command = 0,
|
||||
state_version = state_version + 1,
|
||||
updated_at = NOW()
|
||||
WHERE game_id = $1`,
|
||||
gameID,
|
||||
text,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -130,6 +159,7 @@ func (r *ScreenSessionsRepo) SetTimer(ctx context.Context, gameID int, duration
|
||||
timer_ends_at = NULL,
|
||||
command = 0,
|
||||
state_version = state_version + 1,
|
||||
text = '',
|
||||
updated_at = NOW()
|
||||
WHERE game_id = $1`, gameID, label, duration)
|
||||
return err
|
||||
@@ -194,6 +224,7 @@ func (r *ScreenSessionsRepo) Unbind(ctx context.Context, id int) error {
|
||||
timer_remaining_seconds = 600,
|
||||
timer_state = 1,
|
||||
timer_ends_at = NULL,
|
||||
text = '',
|
||||
state_version = state_version + 1,
|
||||
updated_at = NOW()
|
||||
WHERE id = $1`, id)
|
||||
|
||||
Reference in New Issue
Block a user