From 21ab31b30dcd743625c62562e48ace7327d22793 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Fri, 12 Mar 2021 07:16:11 -0600 Subject: [PATCH] game replace, game list --- src/server/game.go | 14 ++++---------- src/server/game_test.go | 30 ------------------------------ src/server/gamemaster.go | 33 ++++++++++++++++++++++----------- src/server/gamemaster_test.go | 33 +++++++++++++++++++++++++++++++-- src/server/server.go | 34 ++++++++++++++++++++++++++++++++++ src/server/server_test.go | 10 +++++++++- src/server/storage.go | 8 ++++++++ 7 files changed, 108 insertions(+), 54 deletions(-) diff --git a/src/server/game.go b/src/server/game.go index adc7381..667087c 100644 --- a/src/server/game.go +++ b/src/server/game.go @@ -16,10 +16,10 @@ type Game struct { } type Player struct { - ID string - Name string - Card string - Balance Currency + ID string `json:",omitempty"` + Name string `json:",omitempty"` + Card string `json:",omitempty"` + Balance Currency `json:",omitempty"` } type Currency int @@ -34,12 +34,6 @@ func (game Game) GetPlayers() []Player { return players } -func (players Players) MarshalJSON() ([]byte, error) { - game := Game{Players: players} - subplayers := game.GetPlayers() - return json.Marshal(subplayers) -} - func (p Player) Empty() bool { return p == (Player{}) } diff --git a/src/server/game_test.go b/src/server/game_test.go index 268e1c7..bf12463 100644 --- a/src/server/game_test.go +++ b/src/server/game_test.go @@ -5,36 +5,6 @@ import ( "testing" ) -func TestPlayersMarshal(t *testing.T) { - t.Run("0", func(t *testing.T) { - var ps Players - b, err := json.Marshal(ps) - if err != nil { - t.Fatal(err) - } - if s := string(b); s != "[]" { - t.Fatalf("didnt marshal empty Players as []: got %s", s) - } - }) - - t.Run("2", func(t *testing.T) { - var ps Players - ps[3].ID = "hi" - ps[9].ID = "hi2" - b, err := json.Marshal(ps) - if err != nil { - t.Fatal(err) - } - var ps2 []Player - if err := json.Unmarshal(b, &ps2); err != nil { - t.Fatalf("%v: %s", err, b) - } - if len(ps2) != 2 { - t.Fatal(len(ps2)) - } - }) -} - func TestCurrencyMarshal(t *testing.T) { cases := map[string]struct { input Currency diff --git a/src/server/gamemaster.go b/src/server/gamemaster.go index f2e53fe..57c342a 100644 --- a/src/server/gamemaster.go +++ b/src/server/gamemaster.go @@ -14,24 +14,35 @@ func NewGameMaster(config Config, storage *Storage) *GameMaster { } } -func (game *GameMaster) ListGames() ([]string, error) { - return game.storage.ListGames() +func (gm *GameMaster) ListGames() ([]string, error) { + return gm.storage.ListGames() } -func (game *GameMaster) GetGame(id string) (Game, error) { - game.locks.RLock(id) - defer game.locks.RUnlock(id) +func (gm *GameMaster) GetGame(id string) (Game, error) { + gm.locks.RLock(id) + defer gm.locks.RUnlock(id) - return game.storage.GetGame(id) + return gm.storage.GetGame(id) } -func (game *GameMaster) CreateGame(id string) error { - game.locks.Lock(id) - defer game.locks.Unlock(id) +func (gm *GameMaster) CreateGame(id string) error { + gm.locks.Lock(id) + defer gm.locks.Unlock(id) - if _, err := game.storage.GetGame(id); err == nil { + if _, err := gm.storage.GetGame(id); err == nil { return errGameExists } - return game.storage.CreateGame(id) + return gm.storage.CreateGame(id) +} + +func (gm *GameMaster) ReplaceGame(id string, game Game) error { + gm.locks.Lock(id) + defer gm.locks.Unlock(id) + + if _, err := gm.storage.GetGame(id); err != nil { + return err + } + + return gm.storage.ReplaceGame(id, game) } diff --git a/src/server/gamemaster_test.go b/src/server/gamemaster_test.go index e3239ed..f1e7ca2 100644 --- a/src/server/gamemaster_test.go +++ b/src/server/gamemaster_test.go @@ -8,9 +8,8 @@ func mockGameMaster(t *testing.T) *GameMaster { return NewGameMaster(config, storage) } -func TestGameMasterGetCreateGet(t *testing.T) { +func TestGameMasterGetCreateGetList(t *testing.T) { gm := mockGameMaster(t) - id := "game" if games, err := gm.ListGames(); err != nil { @@ -33,3 +32,33 @@ func TestGameMasterGetCreateGet(t *testing.T) { t.Fatal(games) } } + +func TestGameMasterUpdate(t *testing.T) { + gm := mockGameMaster(t) + id := "game" + + err := gm.CreateGame(id) + if err != nil { + t.Fatal(err) + } + + game, err := gm.GetGame(id) + if err != nil { + t.Fatal(err) + } + + game.Players[2].ID = "hi" + game.Pot = 123 + err = gm.ReplaceGame(id, game) + if err != nil { + t.Fatal(err) + } + + game2, err := gm.GetGame(id) + if err != nil { + t.Fatal(err) + } + if game2 != game { + t.Fatalf("replace+get don't match:\nwant\t%+v\ngot\t%+v", game, game2) + } +} diff --git a/src/server/server.go b/src/server/server.go index c6b0983..949c776 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -29,9 +29,13 @@ func (server *Server) Routes() error { fmt.Sprintf("%s/%s%s", server.config.Server.File.Prefix, router.Wildcard, router.Wildcard): map[string]http.HandlerFunc{ http.MethodGet: server.File, }, + fmt.Sprintf("%s/games", server.config.Server.API.Prefix): map[string]http.HandlerFunc{ + http.MethodGet: server.GameList, + }, fmt.Sprintf("%s/games/%s", server.config.Server.API.Prefix, router.Wildcard): map[string]http.HandlerFunc{ http.MethodGet: server.GameGet, http.MethodPost: server.GameInsert, + http.MethodPut: server.GameReplace, }, } @@ -67,6 +71,15 @@ func (server *Server) File(w http.ResponseWriter, r *http.Request) { s.ServeHTTP(w, r) } +func (server *Server) GameList(w http.ResponseWriter, r *http.Request) { + resp, err := server.gm.ListGames() + if err != nil { + internalError(w, err.Error()) + return + } + json.NewEncoder(w).Encode(resp) +} + func (server *Server) GameGet(w http.ResponseWriter, r *http.Request) { var gameID string err := router.Params(r, &gameID) @@ -82,6 +95,27 @@ func (server *Server) GameGet(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(resp) } +func (server *Server) GameReplace(w http.ResponseWriter, r *http.Request) { + var gameID string + err := router.Params(r, &gameID) + if err != nil { + badRequest(w, err.Error()) + return + } + var game Game + err = json.NewDecoder(r.Body).Decode(&game) + if err != nil { + badRequest(w, err.Error()) + return + } + err = server.gm.ReplaceGame(gameID, game) + if err != nil { + internalError(w, err.Error()) + return + } + json.NewEncoder(w).Encode(game) +} + func (server *Server) GameInsert(w http.ResponseWriter, r *http.Request) { var gameID string err := router.Params(r, &gameID) diff --git a/src/server/server_test.go b/src/server/server_test.go index 324854a..593902a 100644 --- a/src/server/server_test.go +++ b/src/server/server_test.go @@ -24,13 +24,21 @@ func TestServerRouter(t *testing.T) { path: path.Join(server.config.Server.File.Prefix), }, "api: games: get": { + method: http.MethodGet, + path: path.Join(server.config.Server.API.Prefix, "games"), + }, + "api: games: id: get": { method: http.MethodGet, path: path.Join(server.config.Server.API.Prefix, "games", "my-game-id"), }, - "api: games: post": { + "api: games: id: post": { method: http.MethodPost, path: path.Join(server.config.Server.API.Prefix, "games", "my-game-id"), }, + "api: games: id: put": { + method: http.MethodPut, + path: path.Join(server.config.Server.API.Prefix, "games", "my-game-id"), + }, } for name, d := range cases { diff --git a/src/server/storage.go b/src/server/storage.go index c675959..7debb34 100644 --- a/src/server/storage.go +++ b/src/server/storage.go @@ -21,6 +21,14 @@ func NewStorage(config Config) *Storage { } } +func (storage Storage) ReplaceGame(id string, game Game) error { + b, err := json.Marshal(game) + if err != nil { + return err + } + return storage.db.Set(id, b, nsGames) +} + func (storage Storage) GetGame(id string) (Game, error) { var game Game