added bw calcs

unfortunately there is an issue with how these are calculated, and they don't
decrease as things quiet down. Well, the bad numbers are their for your
consumption, and should Just Work TM when appropriate changes in
bitbucket.org/smcquay/bandwith land. And they will. But I'm tired now.
This commit is contained in:
Stephen McQuay 2014-03-03 21:57:39 -08:00
parent ecc70606a9
commit 6fd4138740
5 changed files with 73 additions and 15 deletions

View File

@ -57,7 +57,13 @@ func startGame(w http.ResponseWriter, req *http.Request) {
g := games.get(requested_game_name)
if g == nil {
log.Printf("Game '%s' non-existant; making it now", requested_game_name)
g = NewGame(requested_game_name, width, height, obstacles, conf.Tick, maxPoints, mode)
g, err := NewGame(requested_game_name, width, height, obstacles, conf.Tick, maxPoints, mode)
if err != nil {
log.Printf("problem creating game: %s: %s", requested_game_name, err)
b, _ := json.Marshal(NewFailure("game creation failure"))
http.Error(w, string(b), http.StatusConflict)
return
}
go g.run()
games.add(g)
} else {
@ -136,6 +142,33 @@ func gameStats(w http.ResponseWriter, req *http.Request) {
}
}
func bw(w http.ResponseWriter, req *http.Request) {
// TODO: wrap this up in something similar to the JsonHandler to verify the
// url? Look at gorilla routing?
key, err := getGameId(req.URL.Path)
if err != nil {
b, _ := json.Marshal(NewFailure(err.Error()))
http.Error(w, string(b), http.StatusBadRequest)
return
}
log.Printf("requested bandwidth for game: %s", key)
games.RLock()
g, ok := games.m[key]
games.RUnlock()
if !ok {
b, _ := json.Marshal(NewFailure("game not found"))
http.Error(w, string(b), http.StatusNotFound)
return
}
s := map[string][]float64{
"tx": <-g.bw.Tx,
"rx": <-g.bw.Rx,
}
if err := json.NewEncoder(w).Encode(s); 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 {

18
game.go
View File

@ -7,6 +7,8 @@ import (
"sort"
"sync"
"time"
"bitbucket.org/smcquay/bandwidth"
)
const maxPlayer = 128
@ -84,6 +86,7 @@ type game struct {
tick_duration int
stats GameStats
mode GameMode
bw *bandwidth.Bandwidth
}
type GameMode interface {
@ -92,7 +95,16 @@ type GameMode interface {
gameOver(gg *game) (bool, *GameOver)
}
func NewGame(id string, width, height float32, obstacles, tick, maxPoints int, mode string) *game {
func NewGame(id string, width, height float32, obstacles, tick, maxPoints int, mode string) (*game, error) {
bw, err := bandwidth.NewBandwidth(
[]int{1, 10, 60},
time.Duration(500)*time.Millisecond,
)
if err != nil {
log.Fatal("seriously, what the fuck")
return nil, err
}
go bw.Run()
g := &game{
id: id,
register: make(chan *player, maxPlayer),
@ -115,6 +127,7 @@ func NewGame(id string, width, height float32, obstacles, tick, maxPoints int, m
tick_duration: tick,
players_remaining: 2,
stats: GameStats{PlayerStats: make(map[string]*PlayerStats)},
bw: bw,
}
if mode == "melee" {
@ -125,7 +138,7 @@ func NewGame(id string, width, height float32, obstacles, tick, maxPoints int, m
g.mode.setup(g)
return g
return g, nil
}
func (g *game) tick(payload *Boardstate) {
@ -286,6 +299,7 @@ func (g *game) run() {
select {
case <-g.kill:
log.Printf("game %s: received kill signal, dying gracefully", g.id)
close(g.bw.Quit)
games.Lock()
for player := range g.players {
close(player.send)

View File

@ -64,6 +64,7 @@ func main() {
sm.Handle("/game/start/", JsonHandler(startGame))
sm.Handle("/game/list/", JsonHandler(listGames))
sm.Handle("/game/stats/", JsonHandler(gameStats))
sm.Handle("/game/bw/", JsonHandler(bw))
sm.Handle("/game/stop/", JsonHandler(stopGame))
sm.HandleFunc("/fuck/shit/up/", killServer)

View File

@ -1,26 +1,30 @@
package main
import (
"code.google.com/p/go.net/websocket"
"encoding/json"
"errors"
"fmt"
"log"
"bitbucket.org/smcquay/bandwidth"
"code.google.com/p/go.net/websocket"
)
const maxMessageSize = 1024
type protoTalker struct {
ws *websocket.Conn
bw *bandwidth.Bandwidth
send chan Message
buff []byte
Id string
}
func NewProtoTalker(id string, ws *websocket.Conn) *protoTalker {
func NewProtoTalker(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *protoTalker {
return &protoTalker{
send: make(chan Message, 16),
ws: ws,
bw: bw,
Id: id,
buff: make([]byte, maxMessageSize),
}
@ -33,8 +37,8 @@ func (pt *protoTalker) sender() {
if err != nil {
break
}
// XXX: send the count to our bandwidth analyzer ...
_, err = pt.ws.Write(b)
n, err := pt.ws.Write(b)
pt.bw.AddTx <- n
if err != nil {
break
}
@ -50,7 +54,7 @@ func (pt *protoTalker) readJSON(buff []byte) (map[string]Instruction, error) {
log.Printf("%s: problem reading from player: %s", pt.Id, err)
return nil, err
}
// XXX: send n to our bandwidth analyzer ...
pt.bw.AddRx <- n
if n == len(buff) {
errMsg := fmt.Sprintf("%s: read buffer overfull: %s", pt.Id, string(buff))
log.Printf(errMsg)
@ -70,10 +74,10 @@ type player struct {
protoTalker
}
func NewPlayer(id string, ws *websocket.Conn) *player {
func NewPlayer(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *player {
return &player{
Robots: []*Robot{},
protoTalker: *NewProtoTalker(id, ws),
protoTalker: *NewProtoTalker(id, ws, bw),
}
}
@ -152,9 +156,9 @@ type Spectator struct {
protoTalker
}
func NewSpectator(id string, ws *websocket.Conn) *Spectator {
func NewSpectator(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *Spectator {
return &Spectator{
protoTalker: *NewProtoTalker(id, ws),
protoTalker: *NewProtoTalker(id, ws, bw),
}
}

View File

@ -153,7 +153,8 @@ func addPlayer(ws *websocket.Conn) {
game := games.get(gid.Id)
if game == nil {
game = NewGame(
var err error
game, err = NewGame(
gid.Id,
float32(conf.Width),
float32(conf.Height),
@ -162,6 +163,11 @@ func addPlayer(ws *websocket.Conn) {
conf.MaxPoints,
"",
)
if err != nil {
log.Printf("problem creating game: %s", gid.Id)
websocket.JSON.Send(ws, NewFailure("game creation error"))
return
}
go game.run()
games.add(game)
}
@ -230,7 +236,7 @@ func addPlayer(ws *websocket.Conn) {
}
}
p := NewPlayer(player_id, ws)
p := NewPlayer(player_id, ws, game.bw)
log.Printf("%s: made a player: %s", gid.Id, p.Id)
convertedStats := map[string]Stats{}
@ -285,7 +291,7 @@ func addPlayer(ws *websocket.Conn) {
gid.Id,
)
case "spectator":
s := NewSpectator(player_id, ws)
s := NewSpectator(player_id, ws, game.bw)
log.Printf("%s, %s: about to register this spectator", gid.Id, s.Id)
game.sregister <- s
log.Printf("%s, %s: registered spectator", gid.Id, s.Id)