Documentation
¶
Index ¶
- func GenerateCert(cert TLSCert)
- type ClientMessage
- type CurrentQuestion
- type Game
- func (g *Game) Bench(p *Player) error
- func (g *Game) CheckTokenExpiration() error
- func (g *Game) GetPlayer(v any) (*Player, error)
- func (g *Game) GetScoreboard() Scoreboard
- func (g *Game) HasPlayer(name string) (*Player, bool)
- func (g *Game) Unbench(p *Player) error
- func (g *Game) UpdatePlayerScore(socket *websocket.Conn, points int) (int, error)
- type GamePlayers
- type Player
- type PlayerScore
- type Scoreboard
- type ServerMessage
- type Socket
- type SocketServer
- func (s *SocketServer) BaseHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) DefaultHandler(socket *websocket.Conn)
- func (s *SocketServer) GetGame(key string) (*Game, error)
- func (s *SocketServer) GetPlayerBySocket(socket *websocket.Conn) (*Player, *Game, error)
- func (s *SocketServer) HealthHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) KillHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) Message(socket *websocket.Conn, msg ServerMessage) error
- func (s *SocketServer) MessageHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) NotifyHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) Publish(game *Game, msg ServerMessage) error
- func (s *SocketServer) QueryHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) RegisterAndStartGame(game *Game)
- func (s *SocketServer) RegisterGame(game *Game)
- func (s *SocketServer) ResetHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) ScoreboardHandler(w http.ResponseWriter, r *http.Request)
- func (s *SocketServer) StartGame(game *Game)
- func (s *SocketServer) UpdateScoreHandler(w http.ResponseWriter, r *http.Request)
- type TLSCert
- type URL
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GenerateCert ¶
func GenerateCert(cert TLSCert)
Types ¶
type ClientMessage ¶
type ClientMessage struct { Type string `json:"type,omitempty"` Username string `json:"username,omitempty"` Token string `json:"token,omitempty"` Data any `json:"data,omitempty"` }
The socket server unmarshals the response from the browser client into this type.
type CurrentQuestion ¶
type CurrentQuestion struct { Question string `json:"question,omitempty"` Answer any `json:"answer,omitempty"` Choices []string `json:"choices,omitempty"` Weight int `json:"weight,omitempty"` Responses int `json:"responses,omitempty"` }
`Weight` is the amount of points awarded for a correct answer.
type Game ¶
type Game struct { Name string Players GamePlayers Benched GamePlayers Key middleware.APIKey CurrentQuestion }
func (*Game) Bench ¶
This function will move a `Player` out of the game's `Players` pool and into the Benched pool of the Game type. This will occur when a connection is lost due to the browser tab being closed. Since this could have occurred by accident (laptop shuts down, etc), the player should be able to log back into the game and resume where they left off, that is reclaim the points they had when the disconnect occurred. Note that this is different from a player choosing to exit the game by clicking exit or close (TODO).
func (*Game) CheckTokenExpiration ¶
Called only when a new player logs in. It is legal for a logged in player to continue making requests after the game has expired, but not if they have not previously logged in. See [Game.CheckTokenEquality] for more information.
func (*Game) GetPlayer ¶
This function expects either a player name (string) or a player socket (*websocket.Conn). The most reliable way to lookup a player is by their socket, since this cannot be modified by the user. However, when calling an endpoint such as SocketServer.KillHandler, all we have is the player name.
func (*Game) GetScoreboard ¶
func (g *Game) GetScoreboard() Scoreboard
func (*Game) Unbench ¶
If a player logs back in after accidentally killing their browser session (at which point they are "benched"), move their player state from the .Benched pool to the .Players pool in the Game type. This has the effect of allowing them to resume where they left off and regain their points.
func (*Game) UpdatePlayerScore ¶
Called every time a player guesses correctly. Currently, this happens immediately after a correct guess and so every player will see the updated score. This isn't optimal and should be changed to only update after everyone has guessed (TODO).
type GamePlayers ¶
type GamePlayers []*Player
type Player ¶
type Player struct { Location string `json:"location,omitempty"` Name string `json:"name,omitempty"` UUID string `json:"uuid,omitempty"` Score int `json:"score"` Socket *websocket.Conn `json:"conn,omitempty"` }
Players can have a zero `Score`, so don't add the tag `omitempty` when marshaling to the browser.
The `Socket` is the only reliable way to lookup a particular player, and the functions in the package operate on it as often as it can. For example, the `player.Name` could be fiddled with in the browser before sending a request so it could be unreliable.
The `UUID` is set by the client (browser) and sent as part of the websocket URL. It's not currently used.
const socketURL = `{{ . }}?uuid=${getUUID()}`; socket = new WebSocket(socketURL);
type PlayerScore ¶
This is currently for an admin to get a quick view of the game state.
type Scoreboard ¶
type Scoreboard []*PlayerScore
func (Scoreboard) Len ¶
func (s Scoreboard) Len() int
func (Scoreboard) Less ¶
func (s Scoreboard) Less(i, j int) bool
func (Scoreboard) Swap ¶
func (s Scoreboard) Swap(i, j int)
type ServerMessage ¶
This is marshaled to the browser client. See SocketServer.Publish.
type SocketServer ¶
type SocketServer struct { Location URL Games map[string]*Game Tpl *template.Template Mux *http.ServeMux }
A socket server instance is set up to handle multiple (concurrent) games.
func NewSocketServer ¶
func NewSocketServer(url URL) *SocketServer
func (*SocketServer) BaseHandler ¶
func (s *SocketServer) BaseHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) DefaultHandler ¶
func (s *SocketServer) DefaultHandler(socket *websocket.Conn)
func (*SocketServer) GetGame ¶
func (s *SocketServer) GetGame(key string) (*Game, error)
A socket server instance can potentially have multiple games. Note this only checks for token equality **not** expiration.
func (*SocketServer) GetPlayerBySocket ¶
When a connection is suddenly disconnected, for instance when the browser crashes, we don't have any information about the player that closed the session other than the socket. This means that we need to range over all of the games and the players within each game until we find the matching player.
func (*SocketServer) HealthHandler ¶
func (s *SocketServer) HealthHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) KillHandler ¶
func (s *SocketServer) KillHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) Message ¶
func (s *SocketServer) Message(socket *websocket.Conn, msg ServerMessage) error
Notify a single player of an event.
func (*SocketServer) MessageHandler ¶
func (s *SocketServer) MessageHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) NotifyHandler ¶
func (s *SocketServer) NotifyHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) Publish ¶
func (s *SocketServer) Publish(game *Game, msg ServerMessage) error
Notifies every player of an event.
func (*SocketServer) QueryHandler ¶
func (s *SocketServer) QueryHandler(w http.ResponseWriter, r *http.Request)
TODO: Use a CSV package for this?
func (*SocketServer) RegisterAndStartGame ¶
func (s *SocketServer) RegisterAndStartGame(game *Game)
func (*SocketServer) RegisterGame ¶
func (s *SocketServer) RegisterGame(game *Game)
Registers a new game. A socket server can host multiple games.
func (*SocketServer) ResetHandler ¶
func (s *SocketServer) ResetHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) ScoreboardHandler ¶
func (s *SocketServer) ScoreboardHandler(w http.ResponseWriter, r *http.Request)
func (*SocketServer) StartGame ¶
func (s *SocketServer) StartGame(game *Game)
Registers all the handlers with the new mux, adds the middleware and starts starts the game server.
func (*SocketServer) UpdateScoreHandler ¶
func (s *SocketServer) UpdateScoreHandler(w http.ResponseWriter, r *http.Request)
type TLSCert ¶
type TLSCert struct { Host string ValidFrom string ValidFor time.Duration IsCA bool RsaBits int EcdsaCurve string Ed25519Key bool }
Host is the comma-separated hostnames and IPs to generate a certificate for. ValidFrom is start date is the creation date formatted as Jan 1 15:04:05 2011. ValidFor is the time.Duration the certificate is valid for. Defaults to 365*24*time.Hour. IsCA is whether this cert should be its own Certificate Authority. Defaults to false. RsaBits is the size of RSA key to generate. Ignored if Ecdsacurve is set. Defaults to 2048. Ecdsacurve is the ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521. Ed25519Key. Generates an Ed25519 key: Defaults to false.