diff --git a/game/logic.go b/connect4/logic.go
similarity index 95%
rename from game/logic.go
rename to connect4/logic.go
index 7a4d167..8abbb74 100644
--- a/game/logic.go
+++ b/connect4/logic.go
@@ -1,5 +1,5 @@
-// Package game implements Connect 4 game logic, state management, and persistence.
-package game
+// Package connect4 implements Connect 4 game logic, state management, and persistence.
+package connect4
// DropPiece attempts to drop a piece in the given column.
// Returns (row placed, success).
diff --git a/game/persist.go b/connect4/persist.go
similarity index 85%
rename from game/persist.go
rename to connect4/persist.go
index 5efe140..9772b93 100644
--- a/game/persist.go
+++ b/connect4/persist.go
@@ -1,4 +1,4 @@
-package game
+package connect4
import (
"context"
@@ -9,7 +9,7 @@ import (
"github.com/rs/zerolog/log"
)
-func (gi *GameInstance) save() error {
+func (gi *Instance) save() error {
err := saveGame(gi.queries, gi.game)
if err != nil {
log.Error().Err(err).Str("game_id", gi.game.ID).Msg("failed to save game")
@@ -17,8 +17,8 @@ func (gi *GameInstance) save() error {
return err
}
-func (gi *GameInstance) savePlayer(player *Player, slot int) error {
- err := saveGamePlayer(gi.queries, gi.game.ID, player, slot)
+func (gi *Instance) savePlayer(p *Player, slot int) error {
+ err := saveGamePlayer(gi.queries, gi.game.ID, p, slot)
if err != nil {
log.Error().Err(err).Str("game_id", gi.game.ID).Int("slot", slot).Msg("failed to save game player")
}
@@ -48,12 +48,12 @@ func saveGame(queries *repository.Queries, g *Game) error {
})
}
-func saveGamePlayer(queries *repository.Queries, gameID string, player *Player, slot int) error {
+func saveGamePlayer(queries *repository.Queries, gameID string, p *Player, slot int) error {
var userID, guestPlayerID *string
- if player.UserID != nil {
- userID = player.UserID
+ if p.UserID != nil {
+ userID = p.UserID
} else {
- id := string(player.ID)
+ id := string(p.ID)
guestPlayerID = &id
}
@@ -61,8 +61,8 @@ func saveGamePlayer(queries *repository.Queries, gameID string, player *Player,
GameID: gameID,
UserID: userID,
GuestPlayerID: guestPlayerID,
- Nickname: player.Nickname,
- Color: int64(player.Color),
+ Nickname: p.Nickname,
+ Color: int64(p.Color),
Slot: int64(slot),
})
}
@@ -83,13 +83,11 @@ func loadGamePlayers(queries *repository.Queries, id string) ([]*Player, error)
return playersFromRows(rows), nil
}
-// Domain ↔ DB mapping helpers.
-
func gameFromRow(row *repository.Game) (*Game, error) {
g := &Game{
ID: row.ID,
CurrentTurn: int(row.CurrentTurn),
- Status: GameStatus(row.Status),
+ Status: Status(row.Status),
}
if err := g.BoardFromJSON(row.Board); err != nil {
diff --git a/game/store.go b/connect4/store.go
similarity index 59%
rename from game/store.go
rename to connect4/store.go
index 818942c..fe68b1e 100644
--- a/game/store.go
+++ b/connect4/store.go
@@ -1,4 +1,4 @@
-package game
+package connect4
import (
"context"
@@ -12,67 +12,67 @@ type PlayerSession struct {
Player *Player
}
-type GameStore struct {
- games map[string]*GameInstance
+type Store struct {
+ games map[string]*Instance
gamesMu sync.RWMutex
queries *repository.Queries
notifyFunc func(gameID string)
}
-func NewGameStore(queries *repository.Queries) *GameStore {
- return &GameStore{
- games: make(map[string]*GameInstance),
+func NewStore(queries *repository.Queries) *Store {
+ return &Store{
+ games: make(map[string]*Instance),
queries: queries,
}
}
-func (gs *GameStore) SetNotifyFunc(f func(gameID string)) {
- gs.notifyFunc = f
+func (s *Store) SetNotifyFunc(f func(gameID string)) {
+ s.notifyFunc = f
}
-func (gs *GameStore) makeNotify(gameID string) func() {
+func (s *Store) makeNotify(gameID string) func() {
return func() {
- if gs.notifyFunc != nil {
- gs.notifyFunc(gameID)
+ if s.notifyFunc != nil {
+ s.notifyFunc(gameID)
}
}
}
-func (gs *GameStore) Create() *GameInstance {
+func (s *Store) Create() *Instance {
id := player.GenerateID(4)
- gi := NewGameInstance(id)
- gi.queries = gs.queries
- gi.notify = gs.makeNotify(id)
- gs.gamesMu.Lock()
- gs.games[id] = gi
- gs.gamesMu.Unlock()
+ gi := NewInstance(id)
+ gi.queries = s.queries
+ gi.notify = s.makeNotify(id)
+ s.gamesMu.Lock()
+ s.games[id] = gi
+ s.gamesMu.Unlock()
- if gs.queries != nil {
+ if s.queries != nil {
gi.save() //nolint:errcheck
}
return gi
}
-func (gs *GameStore) Get(id string) (*GameInstance, bool) {
- gs.gamesMu.RLock()
- gi, ok := gs.games[id]
- gs.gamesMu.RUnlock()
+func (s *Store) Get(id string) (*Instance, bool) {
+ s.gamesMu.RLock()
+ gi, ok := s.games[id]
+ s.gamesMu.RUnlock()
if ok {
return gi, true
}
- if gs.queries == nil {
+ if s.queries == nil {
return nil, false
}
- g, err := loadGame(gs.queries, id)
+ g, err := loadGame(s.queries, id)
if err != nil || g == nil {
return nil, false
}
- players, _ := loadGamePlayers(gs.queries, id)
+ players, _ := loadGamePlayers(s.queries, id)
for _, p := range players {
switch p.Color {
case 1:
@@ -82,51 +82,51 @@ func (gs *GameStore) Get(id string) (*GameInstance, bool) {
}
}
- gi = &GameInstance{
+ gi = &Instance{
game: g,
- queries: gs.queries,
- notify: gs.makeNotify(id),
+ queries: s.queries,
+ notify: s.makeNotify(id),
}
- gs.gamesMu.Lock()
- gs.games[id] = gi
- gs.gamesMu.Unlock()
+ s.gamesMu.Lock()
+ s.games[id] = gi
+ s.gamesMu.Unlock()
return gi, true
}
-func (gs *GameStore) Delete(id string) error {
- gs.gamesMu.Lock()
- delete(gs.games, id)
- gs.gamesMu.Unlock()
+func (s *Store) Delete(id string) error {
+ s.gamesMu.Lock()
+ delete(s.games, id)
+ s.gamesMu.Unlock()
- if gs.queries != nil {
- return gs.queries.DeleteGame(context.Background(), id)
+ if s.queries != nil {
+ return s.queries.DeleteGame(context.Background(), id)
}
return nil
}
-type GameInstance struct {
+type Instance struct {
game *Game
gameMu sync.RWMutex
notify func()
queries *repository.Queries
}
-func NewGameInstance(id string) *GameInstance {
- return &GameInstance{
+func NewInstance(id string) *Instance {
+ return &Instance{
game: NewGame(id),
notify: func() {},
}
}
-func (gi *GameInstance) ID() string {
+func (gi *Instance) ID() string {
gi.gameMu.RLock()
defer gi.gameMu.RUnlock()
return gi.game.ID
}
-func (gi *GameInstance) Join(ps *PlayerSession) bool {
+func (gi *Instance) Join(ps *PlayerSession) bool {
gi.gameMu.Lock()
defer gi.gameMu.Unlock()
@@ -153,13 +153,13 @@ func (gi *GameInstance) Join(ps *PlayerSession) bool {
return true
}
-func (gi *GameInstance) GetGame() *Game {
+func (gi *Instance) GetGame() *Game {
gi.gameMu.RLock()
defer gi.gameMu.RUnlock()
return gi.game
}
-func (gi *GameInstance) GetPlayerColor(pid player.ID) int {
+func (gi *Instance) GetPlayerColor(pid player.ID) int {
gi.gameMu.RLock()
defer gi.gameMu.RUnlock()
for _, p := range gi.game.Players {
@@ -170,7 +170,7 @@ func (gi *GameInstance) GetPlayerColor(pid player.ID) int {
return 0
}
-func (gi *GameInstance) CreateRematch(gs *GameStore) *GameInstance {
+func (gi *Instance) CreateRematch(s *Store) *Instance {
gi.gameMu.Lock()
defer gi.gameMu.Unlock()
@@ -178,13 +178,13 @@ func (gi *GameInstance) CreateRematch(gs *GameStore) *GameInstance {
return nil
}
- newGI := gs.Create()
+ newGI := s.Create()
newID := newGI.ID()
gi.game.RematchGameID = &newID
if gi.queries != nil {
if err := gi.save(); err != nil {
- gs.Delete(newID) //nolint:errcheck
+ s.Delete(newID) //nolint:errcheck
gi.game.RematchGameID = nil
return nil
}
@@ -194,7 +194,7 @@ func (gi *GameInstance) CreateRematch(gs *GameStore) *GameInstance {
return newGI
}
-func (gi *GameInstance) DropPiece(col int, playerColor int) bool {
+func (gi *Instance) DropPiece(col int, playerColor int) bool {
gi.gameMu.Lock()
defer gi.gameMu.Unlock()
diff --git a/game/types.go b/connect4/types.go
similarity index 93%
rename from game/types.go
rename to connect4/types.go
index 2ceef46..0dac3d8 100644
--- a/game/types.go
+++ b/connect4/types.go
@@ -1,4 +1,4 @@
-package game
+package connect4
import (
"encoding/json"
@@ -13,10 +13,10 @@ type Player struct {
Color int // 1 = Red, 2 = Yellow
}
-type GameStatus int
+type Status int
const (
- StatusWaitingForPlayer GameStatus = iota
+ StatusWaitingForPlayer Status = iota
StatusInProgress
StatusWon
StatusDraw
@@ -27,7 +27,7 @@ type Game struct {
Board [6][7]int // 6 rows, 7 columns; 0=empty, 1=red, 2=yellow
Players [2]*Player // Index 0 = creator (Red), Index 1 = joiner (Yellow)
CurrentTurn int // 1 or 2 (matches player color)
- Status GameStatus
+ Status Status
Winner *Player
WinningCells [][2]int // Coordinates of winning 4 cells for highlighting
RematchGameID *string // ID of the rematch game, if one was created
diff --git a/features/c4game/components/board.templ b/features/c4game/components/board.templ
index ee4cb72..6ac381c 100644
--- a/features/c4game/components/board.templ
+++ b/features/c4game/components/board.templ
@@ -3,11 +3,11 @@ package components
import (
"fmt"
- "github.com/ryanhamamura/c4/game"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/starfederation/datastar-go/datastar"
)
-templ Board(g *game.Game, myColor int) {
+templ Board(g *connect4.Game, myColor int) {
for col := 0; col < 7; col++ {
@column(g, col, myColor)
@@ -15,8 +15,8 @@ templ Board(g *game.Game, myColor int) {
}
-templ column(g *game.Game, colIdx int, myColor int) {
- if g.Status == game.StatusInProgress && myColor == g.CurrentTurn {
+templ column(g *connect4.Game, colIdx int, myColor int) {
+ if g.Status == connect4.StatusInProgress && myColor == g.CurrentTurn {
}
-func cellClass(g *game.Game, row, col int) string {
+func cellClass(g *connect4.Game, row, col int) string {
color := g.Board[row][col]
activeTurn := 0
- if g.Status == game.StatusInProgress {
+ if g.Status == connect4.StatusInProgress {
activeTurn = g.CurrentTurn
}
diff --git a/features/c4game/components/status.templ b/features/c4game/components/status.templ
index d4f4e71..c2e6483 100644
--- a/features/c4game/components/status.templ
+++ b/features/c4game/components/status.templ
@@ -2,11 +2,11 @@ package components
import (
"github.com/ryanhamamura/c4/config"
- "github.com/ryanhamamura/c4/game"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/starfederation/datastar-go/datastar"
)
-templ StatusBanner(g *game.Game, myColor int) {
+templ StatusBanner(g *connect4.Game, myColor int) {
{ statusMessage(g, myColor) }
if g.IsFinished() {
@@ -30,7 +30,7 @@ templ StatusBanner(g *game.Game, myColor int) {
}
-templ PlayerInfo(g *game.Game, myColor int) {
+templ PlayerInfo(g *connect4.Game, myColor int) {
for _, info := range playerInfoPairs(g, myColor) {
@@ -61,36 +61,36 @@ script copyToClipboard(url string) {
navigator.clipboard.writeText(url)
}
-func statusClass(g *game.Game, myColor int) string {
+func statusClass(g *connect4.Game, myColor int) string {
switch g.Status {
- case game.StatusWaitingForPlayer:
+ case connect4.StatusWaitingForPlayer:
return "alert bg-base-200 text-xl font-bold"
- case game.StatusInProgress:
+ case connect4.StatusInProgress:
if g.CurrentTurn == myColor {
return "alert alert-success text-xl font-bold"
}
return "alert bg-base-200 text-xl font-bold"
- case game.StatusWon:
+ case connect4.StatusWon:
if g.Winner != nil && g.Winner.Color == myColor {
return "alert alert-success text-xl font-bold"
}
return "alert alert-error text-xl font-bold"
- case game.StatusDraw:
+ case connect4.StatusDraw:
return "alert alert-warning text-xl font-bold"
}
return "alert bg-base-200 text-xl font-bold"
}
-func statusMessage(g *game.Game, myColor int) string {
+func statusMessage(g *connect4.Game, myColor int) string {
switch g.Status {
- case game.StatusWaitingForPlayer:
+ case connect4.StatusWaitingForPlayer:
return "Waiting for opponent..."
- case game.StatusInProgress:
+ case connect4.StatusInProgress:
if g.CurrentTurn == myColor {
return "Your turn!"
}
return opponentName(g, myColor) + "'s turn"
- case game.StatusWon:
+ case connect4.StatusWon:
if g.Winner != nil && g.Winner.Color == myColor {
return "You win!"
}
@@ -98,13 +98,13 @@ func statusMessage(g *game.Game, myColor int) string {
return g.Winner.Nickname + " wins!"
}
return "Game over"
- case game.StatusDraw:
+ case connect4.StatusDraw:
return "It's a draw!"
}
return ""
}
-func opponentName(g *game.Game, myColor int) string {
+func opponentName(g *connect4.Game, myColor int) string {
for _, p := range g.Players {
if p != nil && p.Color != myColor {
return p.Nickname
@@ -118,7 +118,7 @@ type playerInfoData struct {
Label string
}
-func playerInfoPairs(g *game.Game, myColor int) []playerInfoData {
+func playerInfoPairs(g *connect4.Game, myColor int) []playerInfoData {
var result []playerInfoData
var myName, oppName string
diff --git a/features/c4game/handlers.go b/features/c4game/handlers.go
index 906541a..c82573d 100644
--- a/features/c4game/handlers.go
+++ b/features/c4game/handlers.go
@@ -13,10 +13,10 @@ import (
"github.com/ryanhamamura/c4/chat"
chatcomponents "github.com/ryanhamamura/c4/chat/components"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/db/repository"
"github.com/ryanhamamura/c4/features/c4game/components"
"github.com/ryanhamamura/c4/features/c4game/pages"
- "github.com/ryanhamamura/c4/game"
"github.com/ryanhamamura/c4/sessions"
)
@@ -41,7 +41,7 @@ func c4ChatConfig(gameID string) chatcomponents.Config {
}
}
-func HandleGamePage(store *game.GameStore, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
+func HandleGamePage(store *connect4.Store, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -57,14 +57,14 @@ func HandleGamePage(store *game.GameStore, sm *scs.SessionManager, queries *repo
// Auto-join if player has a nickname but isn't in the game yet
if nickname != "" && gi.GetPlayerColor(playerID) == 0 {
- p := &game.Player{
+ p := &connect4.Player{
ID: playerID,
Nickname: nickname,
}
if userID != "" {
p.UserID = &userID
}
- gi.Join(&game.PlayerSession{Player: p})
+ gi.Join(&connect4.PlayerSession{Player: p})
}
myColor := gi.GetPlayerColor(playerID)
@@ -93,7 +93,7 @@ func HandleGamePage(store *game.GameStore, sm *scs.SessionManager, queries *repo
}
}
-func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
+func HandleGameEvents(store *connect4.Store, nc *nats.Conn, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -111,14 +111,14 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManag
))
chatCfg := c4ChatConfig(gameID)
- room := chat.NewRoom(nc, "game.chat."+gameID, chat.LoadMessages(queries, gameID))
+ room := chat.NewRoom(nc, "connect4.chat."+gameID, chat.LoadMessages(queries, gameID))
// Send initial render
sendGameComponents(sse, gi, myColor, room, chatCfg)
// Subscribe to game state updates
gameCh := make(chan *nats.Msg, 64)
- gameSub, err := nc.ChanSubscribe("game."+gameID, gameCh)
+ gameSub, err := nc.ChanSubscribe("connect4."+gameID, gameCh)
if err != nil {
return
}
@@ -152,7 +152,7 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManag
}
}
-func HandleDropPiece(store *game.GameStore, sm *scs.SessionManager) http.HandlerFunc {
+func HandleDropPiece(store *connect4.Store, sm *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -181,7 +181,7 @@ func HandleDropPiece(store *game.GameStore, sm *scs.SessionManager) http.Handler
}
}
-func HandleSendChat(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
+func HandleSendChat(store *connect4.Store, nc *nats.Conn, sm *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -230,7 +230,7 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManager
}
chat.SaveMessage(queries, gameID, msg)
- room := chat.NewRoom(nc, "game.chat."+gameID, nil)
+ room := chat.NewRoom(nc, "connect4.chat."+gameID, nil)
room.Send(msg)
sse := datastar.NewSSE(w, r)
@@ -238,7 +238,7 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sm *scs.SessionManager
}
}
-func HandleSetNickname(store *game.GameStore, sm *scs.SessionManager) http.HandlerFunc {
+func HandleSetNickname(store *connect4.Store, sm *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -269,14 +269,14 @@ func HandleSetNickname(store *game.GameStore, sm *scs.SessionManager) http.Handl
userID := sessions.GetUserID(sm, r)
if gi.GetPlayerColor(playerID) == 0 {
- p := &game.Player{
+ p := &connect4.Player{
ID: playerID,
Nickname: signals.Nickname,
}
if userID != "" {
p.UserID = &userID
}
- gi.Join(&game.PlayerSession{Player: p})
+ gi.Join(&connect4.PlayerSession{Player: p})
}
sse := datastar.NewSSE(w, r)
@@ -284,7 +284,7 @@ func HandleSetNickname(store *game.GameStore, sm *scs.SessionManager) http.Handl
}
}
-func HandleRematch(store *game.GameStore, sm *scs.SessionManager) http.HandlerFunc {
+func HandleRematch(store *connect4.Store, sm *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
@@ -304,7 +304,7 @@ func HandleRematch(store *game.GameStore, sm *scs.SessionManager) http.HandlerFu
}
// sendGameComponents patches all game-related SSE components.
-func sendGameComponents(sse *datastar.ServerSentEventGenerator, gi *game.GameInstance, myColor int, room *chat.Room, chatCfg chatcomponents.Config) {
+func sendGameComponents(sse *datastar.ServerSentEventGenerator, gi *connect4.Instance, myColor int, room *chat.Room, chatCfg chatcomponents.Config) {
g := gi.GetGame()
sse.PatchElementTempl(components.Board(g, myColor), datastar.WithSelectorID("c4-board")) //nolint:errcheck
diff --git a/features/c4game/pages/game.templ b/features/c4game/pages/game.templ
index eee6222..19d8418 100644
--- a/features/c4game/pages/game.templ
+++ b/features/c4game/pages/game.templ
@@ -3,14 +3,14 @@ package pages
import (
"github.com/ryanhamamura/c4/chat"
chatcomponents "github.com/ryanhamamura/c4/chat/components"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/features/c4game/components"
sharedcomponents "github.com/ryanhamamura/c4/features/common/components"
"github.com/ryanhamamura/c4/features/common/layouts"
- "github.com/ryanhamamura/c4/game"
"github.com/starfederation/datastar-go/datastar"
)
-templ GamePage(g *game.Game, myColor int, messages []chat.Message, chatCfg chatcomponents.Config) {
+templ GamePage(g *connect4.Game, myColor int, messages []chat.Message, chatCfg chatcomponents.Config) {
@layouts.Base("Connect 4") {
- if g.Status == game.StatusWaitingForPlayer {
+ if g.Status == connect4.StatusWaitingForPlayer {
@components.InviteLink(g.ID)
}
diff --git a/features/c4game/routes.go b/features/c4game/routes.go
index 2ffd2dc..bc35047 100644
--- a/features/c4game/routes.go
+++ b/features/c4game/routes.go
@@ -6,13 +6,13 @@ import (
"github.com/go-chi/chi/v5"
"github.com/nats-io/nats.go"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/db/repository"
- "github.com/ryanhamamura/c4/game"
)
func SetupRoutes(
router chi.Router,
- store *game.GameStore,
+ store *connect4.Store,
nc *nats.Conn,
sessions *scs.SessionManager,
queries *repository.Queries,
diff --git a/features/lobby/components/gamelist.templ b/features/lobby/components/gamelist.templ
index 24563e5..3fbcb5c 100644
--- a/features/lobby/components/gamelist.templ
+++ b/features/lobby/components/gamelist.templ
@@ -4,7 +4,7 @@ import (
"fmt"
"time"
- "github.com/ryanhamamura/c4/game"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/starfederation/datastar-go/datastar"
)
@@ -46,10 +46,10 @@ templ gameListEntry(g GameListItem) {
}
func statusText(g GameListItem) string {
- switch game.GameStatus(g.Status) {
- case game.StatusWaitingForPlayer:
+ switch connect4.Status(g.Status) {
+ case connect4.StatusWaitingForPlayer:
return "Waiting for opponent"
- case game.StatusInProgress:
+ case connect4.StatusInProgress:
if g.IsMyTurn {
return "Your turn!"
}
@@ -59,10 +59,10 @@ func statusText(g GameListItem) string {
}
func statusClass(g GameListItem) string {
- switch game.GameStatus(g.Status) {
- case game.StatusWaitingForPlayer:
+ switch connect4.Status(g.Status) {
+ case connect4.StatusWaitingForPlayer:
return "text-sm opacity-60"
- case game.StatusInProgress:
+ case connect4.StatusInProgress:
if g.IsMyTurn {
return "text-sm text-success font-bold"
}
diff --git a/features/lobby/handlers.go b/features/lobby/handlers.go
index 938c02a..609eee3 100644
--- a/features/lobby/handlers.go
+++ b/features/lobby/handlers.go
@@ -7,10 +7,10 @@ import (
"strconv"
"time"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/db/repository"
lobbycomponents "github.com/ryanhamamura/c4/features/lobby/components"
"github.com/ryanhamamura/c4/features/lobby/pages"
- "github.com/ryanhamamura/c4/game"
"github.com/ryanhamamura/c4/snake"
"github.com/alexedwards/scs/v2"
@@ -80,7 +80,7 @@ func HandleLobbyPage(queries *repository.Queries, sessions *scs.SessionManager,
}
// HandleCreateGame reads the nickname signal, creates a connect4 game, and redirects via SSE.
-func HandleCreateGame(store *game.GameStore, sessions *scs.SessionManager) http.HandlerFunc {
+func HandleCreateGame(store *connect4.Store, sessions *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
type Signals struct {
Nickname string `json:"nickname"`
@@ -104,7 +104,7 @@ func HandleCreateGame(store *game.GameStore, sessions *scs.SessionManager) http.
}
// HandleDeleteGame deletes a connect4 game and redirects to the lobby.
-func HandleDeleteGame(store *game.GameStore, sessions *scs.SessionManager) http.HandlerFunc {
+func HandleDeleteGame(store *connect4.Store, sessions *scs.SessionManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gameID := chi.URLParam(r, "id")
if gameID == "" {
diff --git a/features/lobby/routes.go b/features/lobby/routes.go
index ea8a433..103f3de 100644
--- a/features/lobby/routes.go
+++ b/features/lobby/routes.go
@@ -2,8 +2,8 @@
package lobby
import (
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/db/repository"
- "github.com/ryanhamamura/c4/game"
"github.com/ryanhamamura/c4/snake"
"github.com/alexedwards/scs/v2"
@@ -14,7 +14,7 @@ func SetupRoutes(
router chi.Router,
queries *repository.Queries,
sessions *scs.SessionManager,
- store *game.GameStore,
+ store *connect4.Store,
snakeStore *snake.SnakeStore,
) {
router.Get("/", HandleLobbyPage(queries, sessions, snakeStore))
diff --git a/main.go b/main.go
index 1b97103..04c3f51 100644
--- a/main.go
+++ b/main.go
@@ -12,9 +12,9 @@ import (
"time"
"github.com/ryanhamamura/c4/config"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/db"
"github.com/ryanhamamura/c4/db/repository"
- "github.com/ryanhamamura/c4/game"
"github.com/ryanhamamura/c4/logging"
appnats "github.com/ryanhamamura/c4/nats"
"github.com/ryanhamamura/c4/router"
@@ -71,9 +71,9 @@ func run(ctx context.Context) error {
defer cleanupNATS()
// Game stores
- store := game.NewGameStore(queries)
+ store := connect4.NewStore(queries)
store.SetNotifyFunc(func(gameID string) {
- nc.Publish("game."+gameID, nil) //nolint:errcheck // best-effort notification
+ nc.Publish("connect4."+gameID, nil) //nolint:errcheck // best-effort notification
})
snakeStore := snake.NewSnakeStore(queries)
diff --git a/router/router.go b/router/router.go
index 6f8b6eb..ce62137 100644
--- a/router/router.go
+++ b/router/router.go
@@ -8,12 +8,12 @@ import (
"sync"
"github.com/ryanhamamura/c4/config"
+ "github.com/ryanhamamura/c4/connect4"
"github.com/ryanhamamura/c4/db/repository"
"github.com/ryanhamamura/c4/features/auth"
"github.com/ryanhamamura/c4/features/c4game"
"github.com/ryanhamamura/c4/features/lobby"
"github.com/ryanhamamura/c4/features/snakegame"
- "github.com/ryanhamamura/c4/game"
"github.com/ryanhamamura/c4/snake"
"github.com/alexedwards/scs/v2"
@@ -27,7 +27,7 @@ func SetupRoutes(
queries *repository.Queries,
sessions *scs.SessionManager,
nc *nats.Conn,
- store *game.GameStore,
+ store *connect4.Store,
snakeStore *snake.SnakeStore,
assets embed.FS,
) {