// Package services provides the game service layer for Connect 4, // handling NATS subscriptions and chat room management. package services import ( "fmt" "github.com/nats-io/nats.go" "github.com/ryanhamamura/games/chat" chatcomponents "github.com/ryanhamamura/games/chat/components" "github.com/ryanhamamura/games/connect4" "github.com/ryanhamamura/games/db/repository" ) // c4ChatColors maps player slot (0-indexed) to CSS background colors. var c4ChatColors = map[int]string{ 0: "#4a2a3a", // Red player 1: "#2a4545", // Yellow player } func c4ChatColor(slot int) string { if c, ok := c4ChatColors[slot]; ok { return c } return "#666" } // GameService manages NATS subscriptions and chat for Connect 4 games. type GameService struct { nc *nats.Conn queries *repository.Queries } // NewGameService creates a new game service. func NewGameService(nc *nats.Conn, queries *repository.Queries) *GameService { return &GameService{ nc: nc, queries: queries, } } // SubscribeGameUpdates returns a NATS subscription and channel for game state updates. func (s *GameService) SubscribeGameUpdates(gameID string) (*nats.Subscription, <-chan *nats.Msg, error) { ch := make(chan *nats.Msg, 64) sub, err := s.nc.ChanSubscribe(connect4.GameSubject(gameID), ch) if err != nil { return nil, nil, fmt.Errorf("subscribing to game updates: %w", err) } return sub, ch, nil } // ChatConfig returns the chat configuration for a game. func (s *GameService) ChatConfig(gameID string) chatcomponents.Config { return chatcomponents.Config{ CSSPrefix: "c4", PostURL: fmt.Sprintf("/games/%s/chat", gameID), Color: c4ChatColor, } } // ChatRoom returns a persistent chat room for a game. func (s *GameService) ChatRoom(gameID string) *chat.Room { return chat.NewPersistentRoom(s.nc, connect4.ChatSubject(gameID), s.queries, gameID) } // PublishGameUpdate sends a notification that the game state has changed. func (s *GameService) PublishGameUpdate(gameID string) error { return s.nc.Publish(connect4.GameSubject(gameID), nil) }