added simple game stats

This commit is contained in:
Stephen McQuay 2013-11-13 23:45:02 -08:00
parent 84ed6c9c32
commit 245c483f9e
4 changed files with 84 additions and 29 deletions

View File

@ -2,6 +2,8 @@ package main
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http" "net/http"
@ -105,23 +107,49 @@ func listGames(w http.ResponseWriter, req *http.Request) {
} }
} }
func stopGame(w http.ResponseWriter, req *http.Request) { func gameStats(w http.ResponseWriter, req *http.Request) {
trimmed := strings.Trim(req.URL.Path, "/") key, err := getGameId(req.URL.Path)
fullPath := strings.Split(trimmed, "/") if err != nil {
log.Println(req.URL.Path)
if len(fullPath) != 3 {
http.Error(w, "improperly formed url", http.StatusBadRequest) http.Error(w, "improperly formed url", http.StatusBadRequest)
}
log.Printf("requested stats for game: %s", key)
games.RLock()
g, ok := games.m[key]
games.RUnlock()
if !ok {
http.NotFound(w, req)
return return
} }
key := fullPath[2] g.winners.RLock()
defer g.winners.RUnlock()
if err := json.NewEncoder(w).Encode(g.winners.m); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func stopGame(w http.ResponseWriter, req *http.Request) {
key, err := getGameId(req.URL.Path)
if err != nil {
http.Error(w, "improperly formed url", http.StatusBadRequest)
}
games.Lock() games.Lock()
gameid, ok := games.m[key] g, ok := games.m[key]
defer games.Unlock() defer games.Unlock()
if !ok { if !ok {
http.NotFound(w, req) http.NotFound(w, req)
return return
} }
gameid.kill <- true g.kill <- true
message := struct {
Ok bool `json:"ok"`
Message string `json:"message"`
}{
Ok: true,
Message: fmt.Sprintf("Successfully stopped game: %s", key),
}
if err := json.NewEncoder(w).Encode(message); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
} }
func killServer(w http.ResponseWriter, req *http.Request) { func killServer(w http.ResponseWriter, req *http.Request) {
@ -146,3 +174,14 @@ func index(w http.ResponseWriter, req *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
func getGameId(path string) (string, error) {
var err error
trimmed := strings.Trim(path, "/")
fullPath := strings.Split(trimmed, "/")
if len(fullPath) != 3 {
return "", errors.New("improperly formed url")
}
key := fullPath[2]
return key, err
}

49
game.go
View File

@ -40,6 +40,11 @@ func (ml *MapLock) add(g *game) {
ml.Unlock() ml.Unlock()
} }
type WinnerMap struct {
m map[string]int
sync.RWMutex
}
type game struct { type game struct {
id string id string
players map[*player]bool players map[*player]bool
@ -58,27 +63,30 @@ type game struct {
repair_hp int repair_hp int
repair_rate float32 repair_rate float32
tick_duration int tick_duration int
winners WinnerMap
} }
func NewGame(id string, width, height float32, tick int) *game { func NewGame(id string, width, height float32, tick int) *game {
g := &game{ g := &game{
id: id, id: id,
register: make(chan *player), register: make(chan *player),
unregister: make(chan *player, maxPlayer), unregister: make(chan *player, maxPlayer),
projectiles: make(map[*Projectile]bool), projectiles: make(map[*Projectile]bool),
splosions: make(map[*Splosion]bool), splosions: make(map[*Splosion]bool),
obstacles: GenerateObstacles(conf.Obstacles, width, height), obstacles: GenerateObstacles(conf.Obstacles, width, height),
players: make(map[*player]bool), players: make(map[*player]bool),
turn: 0, turn: 0,
width: width, width: width,
height: height, height: height,
spectators: make(map[*Spectator]bool), spectators: make(map[*Spectator]bool),
sregister: make(chan *Spectator), sregister: make(chan *Spectator),
sunregister: make(chan *Spectator), sunregister: make(chan *Spectator),
kill: make(chan bool, maxPlayer), kill: make(chan bool, maxPlayer),
repair_hp: 5, repair_hp: 5,
repair_rate: 3.0, repair_rate: 3.0,
tick_duration: tick, tick_duration: tick,
players_remaining: 2,
winners: WinnerMap{m: make(map[string]int)},
} }
return g return g
} }
@ -284,16 +292,21 @@ func (g *game) run() {
func (g *game) gameOver() (bool, *GameOver) { func (g *game) gameOver() (bool, *GameOver) {
over := false over := false
stats := NewGameOver() var stats *GameOver
if g.players_remaining <= 1 && len(g.players) > 1 { if g.players_remaining <= 1 && len(g.players) > 1 {
g.obstacles = GenerateObstacles(conf.Obstacles, g.width, g.height) g.obstacles = GenerateObstacles(conf.Obstacles, g.width, g.height)
log.Printf("game %s: game over", g.id) log.Printf("game %s: game over", g.id)
stats = NewGameOver()
for p := range g.players { for p := range g.players {
for _, r := range p.Robots { for _, r := range p.Robots {
if r.Health > 0 { if r.Health > 0 {
log.Printf("Robot %v Survived", r.Id) log.Printf("Robot %v Survived", r.Id)
g.winners.Lock()
g.winners.m[r.Id] += 1
g.winners.Unlock()
stats.Winners = append(stats.Winners, r.Id)
} }
r.reset(g) r.reset(g)
} }

View File

@ -63,7 +63,8 @@ func main() {
sm.Handle("/ws/", websocket.Handler(addPlayer)) sm.Handle("/ws/", websocket.Handler(addPlayer))
sm.Handle("/game/start/", JsonHandler(startGame)) sm.Handle("/game/start/", JsonHandler(startGame))
sm.Handle("/game/list/", JsonHandler(listGames)) sm.Handle("/game/list/", JsonHandler(listGames))
sm.HandleFunc("/game/stop/", stopGame) sm.Handle("/game/stats/", JsonHandler(gameStats))
sm.Handle("/game/stop/", JsonHandler(stopGame))
sm.HandleFunc("/fuck/shit/up/", killServer) sm.HandleFunc("/fuck/shit/up/", killServer)
err = http.ListenAndServe(*addr, sm) err = http.ListenAndServe(*addr, sm)

View File

@ -128,12 +128,14 @@ func NewBoardstate() *Boardstate {
} }
type GameOver struct { type GameOver struct {
Type string `json:"type"` Winners []string `json:"winners"`
Type string `json:"type"`
} }
func NewGameOver() *GameOver { func NewGameOver() *GameOver {
return &GameOver{ return &GameOver{
Type: "gameover", Type: "gameover",
Winners: make([]string, 0),
} }
} }