Skip to content

Commit

Permalink
feat: spectator support on game state
Browse files Browse the repository at this point in the history
  • Loading branch information
daithihearn committed Feb 2, 2024
1 parent c5315c8 commit 853c4a3
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 147 deletions.
24 changes: 4 additions & 20 deletions pkg/game/game-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,7 @@ func (h *Handler) Call(c *gin.Context) {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state, err := game.GetState(id)
if err != nil {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state := game.GetState(id)
c.IndentedJSON(http.StatusOK, state)
}

Expand Down Expand Up @@ -313,11 +309,7 @@ func (h *Handler) SelectSuit(c *gin.Context) {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state, err := game.GetState(id)
if err != nil {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state := game.GetState(id)
c.IndentedJSON(http.StatusOK, state)
}

Expand Down Expand Up @@ -364,11 +356,7 @@ func (h *Handler) Buy(c *gin.Context) {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state, err := game.GetState(id)
if err != nil {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state := game.GetState(id)
c.IndentedJSON(http.StatusOK, state)
}

Expand Down Expand Up @@ -417,10 +405,6 @@ func (h *Handler) Play(c *gin.Context) {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state, err := game.GetState(id)
if err != nil {
c.JSON(http.StatusInternalServerError, api.ErrorResponse{Message: err.Error()})
return
}
state := game.GetState(id)
c.IndentedJSON(http.StatusOK, state)
}
63 changes: 31 additions & 32 deletions pkg/game/game-methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,45 @@ func (g *Game) Me(playerID string) (Player, error) {
return Player{}, fmt.Errorf("player not found in game")
}

func (g *Game) GetState(playerID string) (State, error) {
// Get player
me, err := g.Me(playerID)
if err != nil {
return State{}, err
func (g *Game) GetState(playerID string) State {
// 1. Get Previous round if there is one
var prevRound Round
if len(g.Completed) > 0 {
prevRound = g.Completed[len(g.Completed)-1]
}

// 1. Get max call
// 2. Get max call
maxCall := Pass
for _, p := range g.Players {
if p.Call > maxCall {
maxCall = p.Call
}
}

// 2. Add dummy if applicable
// 3. Get player
me, err := g.Me(playerID)

// If the player isn't in the game they are a spectator
if err != nil {
return State{
ID: g.ID,
Revision: g.Revision,
IamSpectator: true,
Status: g.Status,
Round: g.CurrentRound,
PrevRound: prevRound,
MaxCall: maxCall,
Players: g.Players,
}
}

// 4. Add dummy if applicable
iamGoer := g.CurrentRound.GoerID == playerID
if iamGoer && g.CurrentRound.Status == Called && g.Dummy != nil {
me.Cards = append(me.Cards, g.Dummy...)
}

// 3. Get Previous round if there is one
var prevRound Round
if len(g.Completed) > 0 {
prevRound = g.Completed[len(g.Completed)-1]
}

// 4. Return player's game state
// 5. Return player's game state
gameState := State{
ID: g.ID,
Revision: g.Revision,
Expand All @@ -60,7 +71,7 @@ func (g *Game) GetState(playerID string) (State, error) {
Players: g.Players,
}

return gameState, nil
return gameState
}

// MinKeep returns the minimum number of cards that must be kept by a player
Expand Down Expand Up @@ -280,10 +291,7 @@ func (g *Game) Call(playerID string, call Call) error {
}

// If they are in the bunker (score < -30) they can only pass
state, err := g.GetState(playerID)
if err != nil {
return err
}
state := g.GetState(playerID)
if state.Me.Score < -30 && call != Pass {
return fmt.Errorf("player in bunker")
}
Expand Down Expand Up @@ -429,10 +437,7 @@ func (g *Game) SelectSuit(playerID string, suit Suit, cards []CardName) error {
}

// Verify the cards are valid (must be either in the player's hand or the dummy's hand and must be unique
state, errS := g.GetState(playerID)
if errS != nil {
return errS
}
state := g.GetState(playerID)
if !containsAllUnique(state.Cards, cards) {
return fmt.Errorf("invalid card selected")
}
Expand Down Expand Up @@ -482,10 +487,7 @@ func (g *Game) Buy(playerID string, cards []CardName) error {
}

// Verify the cards are valid (must be either in the player's hand or the dummy's hand and must be unique
state, errS := g.GetState(playerID)
if errS != nil {
return errS
}
state := g.GetState(playerID)
if !containsAllUnique(state.Cards, cards) {
return fmt.Errorf("invalid card selected")
}
Expand Down Expand Up @@ -543,10 +545,7 @@ func (g *Game) Play(id string, card CardName) error {
}

// Verify the card is valid
state, err := g.GetState(id)
if err != nil {
return err
}
state := g.GetState(id)
if !contains(state.Cards, card) {
return fmt.Errorf("invalid card selected")
}
Expand Down Expand Up @@ -592,7 +591,7 @@ func (g *Game) Play(id string, card CardName) error {
g.CurrentRound.CurrentHand.CurrentPlayerID = np.ID
} else {

err = g.completeHand()
err := g.completeHand()
if err != nil {
return err
}
Expand Down
10 changes: 2 additions & 8 deletions pkg/game/game-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ func getCacheKey(gameId string, playerId string) string {
func (s *Service) updateStateCache(game Game) error {
// Update the state cache for all players in the game.
for _, player := range game.Players {
state, err := game.GetState(player.ID)
if err != nil {
return err
}
state := game.GetState(player.ID)
errC := s.Cache.Set(getCacheKey(game.ID, player.ID), state, time.Minute)
if errC != nil {
return errC
Expand Down Expand Up @@ -92,10 +89,7 @@ func (s *Service) GetState(ctx context.Context, gameId string, playerID string)
return State{}, has, errG
}

state, err = game.GetState(playerID)
if err != nil {
return State{}, true, err
}
state = game.GetState(playerID)

// Update the state cache for all players in the game.
errC := s.updateStateCache(game)
Expand Down
15 changes: 12 additions & 3 deletions pkg/game/game-service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func TestGameService_GetState(t *testing.T) {
expectingError: true,
},
{
name: "player not in the game",
name: "player not in the game should be a spectator",
gameID: TwoPlayerGame().ID,
playerID: "3",
mockGetResult: &[]Game{
Expand All @@ -332,8 +332,17 @@ func TestGameService_GetState(t *testing.T) {
mockGetCacheExists: &[]bool{false},
mockGetCacheError: &[]error{nil},
mockSetCacheError: &[]error{nil},
expectedExists: false,
expectingError: true,
expectedResult: State{
ID: TwoPlayerGame().ID,
Revision: TwoPlayerGame().Revision,
IamSpectator: true,
Status: TwoPlayerGame().Status,
Round: TwoPlayerGame().CurrentRound,
MaxCall: TwoPlayerGame().Players[0].Call,
Players: TwoPlayerGame().Players,
},
expectedExists: true,
expectingError: false,
},
{
name: "successful cache hit",
Expand Down
Loading

0 comments on commit 853c4a3

Please sign in to comment.