Add match listing API
This commit is contained in:
parent
2493c76bdf
commit
d0f8b45b0f
4 changed files with 78 additions and 16 deletions
|
@ -288,6 +288,26 @@ func (g *serverGame) opponent(client *serverClient) *serverClient {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *serverGame) listing(playerName []byte) *bgammon.GameListing {
|
||||
if g.terminated() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var playerCount int
|
||||
if len(g.allowed1) != 0 && (len(playerName) == 0 || (!bytes.Equal(g.allowed1, playerName) && !bytes.Equal(g.allowed2, playerName))) {
|
||||
playerCount = 2
|
||||
} else {
|
||||
playerCount = g.playerCount()
|
||||
}
|
||||
return &bgammon.GameListing{
|
||||
ID: g.id,
|
||||
Points: g.Points,
|
||||
Password: len(g.password) != 0,
|
||||
Players: playerCount,
|
||||
Name: string(g.name),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *serverGame) terminated() bool {
|
||||
return g.client1 == nil && g.client2 == nil
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@ func main() {
|
|||
tcpAddress string
|
||||
wsAddress string
|
||||
debug int
|
||||
debugCommands bool
|
||||
rollStatistics bool
|
||||
)
|
||||
flag.StringVar(&tcpAddress, "tcp", "localhost:1337", "TCP listen address")
|
||||
flag.StringVar(&wsAddress, "ws", "localhost:1338", "WebSocket listen address")
|
||||
flag.IntVar(&debug, "debug", 0, "print debug information and serve pprof on specified port")
|
||||
flag.BoolVar(&debugCommands, "debug-commands", false, "allow players to use restricted commands")
|
||||
flag.BoolVar(&rollStatistics, "statistics", false, "print dice roll statistics and exit")
|
||||
flag.Parse()
|
||||
|
||||
|
@ -36,6 +38,10 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
if debugCommands {
|
||||
allowDebugCommands = debugCommands
|
||||
}
|
||||
|
||||
s := newServer()
|
||||
if tcpAddress != "" {
|
||||
s.listen("tcp", tcpAddress)
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
|
@ -42,6 +43,10 @@ type server struct {
|
|||
|
||||
gamesLock sync.RWMutex
|
||||
clientsLock sync.Mutex
|
||||
|
||||
gamesCache []byte
|
||||
gamesCacheTime time.Time
|
||||
gamesCacheLock sync.Mutex
|
||||
}
|
||||
|
||||
func newServer() *server {
|
||||
|
@ -59,6 +64,44 @@ func newServer() *server {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *server) cachedMatches() []byte {
|
||||
s.gamesCacheLock.Lock()
|
||||
defer s.gamesCacheLock.Unlock()
|
||||
|
||||
if time.Since(s.gamesCacheTime) < 5*time.Second {
|
||||
return s.gamesCache
|
||||
}
|
||||
|
||||
s.gamesLock.Lock()
|
||||
defer s.gamesLock.Unlock()
|
||||
|
||||
var games []*bgammon.GameListing
|
||||
for _, g := range s.games {
|
||||
listing := g.listing(nil)
|
||||
if listing == nil || listing.Password || listing.Players == 2 {
|
||||
continue
|
||||
}
|
||||
games = append(games, listing)
|
||||
}
|
||||
|
||||
s.gamesCacheTime = time.Now()
|
||||
if len(games) == 0 {
|
||||
s.gamesCache = []byte("[]")
|
||||
return s.gamesCache
|
||||
}
|
||||
var err error
|
||||
s.gamesCache, err = json.Marshal(games)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal %+v: %s", games, err)
|
||||
}
|
||||
return s.gamesCache
|
||||
}
|
||||
|
||||
func (s *server) handleListMatches(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(s.cachedMatches())
|
||||
}
|
||||
|
||||
func (s *server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
||||
const bufferSize = 8
|
||||
commands := make(chan []byte, bufferSize)
|
||||
|
@ -84,7 +127,12 @@ func (s *server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func (s *server) listenWebSocket(address string) {
|
||||
log.Printf("Listening for WebSocket connections on %s...", address)
|
||||
err := http.ListenAndServe(address, http.HandlerFunc(s.handleWebSocket))
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/matches", s.handleListMatches)
|
||||
mux.HandleFunc("/", s.handleWebSocket)
|
||||
|
||||
err := http.ListenAndServe(address, mux)
|
||||
log.Fatalf("failed to listen on %s: %s", address, err)
|
||||
}
|
||||
|
||||
|
@ -456,23 +504,12 @@ COMMANDS:
|
|||
ev := &bgammon.EventList{}
|
||||
|
||||
s.gamesLock.RLock()
|
||||
var playerCount int
|
||||
for _, g := range s.games {
|
||||
if g.terminated() {
|
||||
listing := g.listing(cmd.client.name)
|
||||
if listing == nil {
|
||||
continue
|
||||
}
|
||||
if len(g.allowed1) != 0 && !bytes.Equal(g.allowed1, cmd.client.name) && !bytes.Equal(g.allowed2, cmd.client.name) {
|
||||
playerCount = 2
|
||||
} else {
|
||||
playerCount = g.playerCount()
|
||||
}
|
||||
ev.Games = append(ev.Games, bgammon.GameListing{
|
||||
ID: g.id,
|
||||
Points: g.Points,
|
||||
Password: len(g.password) != 0,
|
||||
Players: playerCount,
|
||||
Name: string(g.name),
|
||||
})
|
||||
ev.Games = append(ev.Games, *listing)
|
||||
}
|
||||
s.gamesLock.RUnlock()
|
||||
|
||||
|
|
1
event.go
1
event.go
|
@ -41,7 +41,6 @@ type EventSay struct {
|
|||
}
|
||||
|
||||
type GameListing struct {
|
||||
Event
|
||||
ID int
|
||||
Password bool
|
||||
Points int
|
||||
|
|
Loading…
Reference in a new issue