game replace, game list

This commit is contained in:
Bel LaPointe
2021-03-12 07:16:11 -06:00
parent aaf4ff3161
commit 21ab31b30d
7 changed files with 108 additions and 54 deletions

View File

@@ -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{})
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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