trivia

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2023 License: GPL-3.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIKey

type APIKey struct {
	Key         string
	TimeCreated time.Time
	Expiration  float64
	Expired     bool
}

type ClientMessage

type ClientMessage struct {
	Type     string      `json:"type,omitempty"`
	Username string      `json:"username,omitempty"`
	Token    string      `json:"token,omitempty"`
	Data     interface{} `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   string   `json:"answer,omitempty"`
	Choices  []string `json:"choices,omitempty"`
	Weight   int      `json:"weight,omitempty"`
}

`Weight` is the amount of points awarded for a correct answer.

type Game

type Game struct {
	Name    string
	Players GamePlayers
	Benched GamePlayers
	Key     APIKey
	CurrentQuestion
}

func NewGame

func NewGame(name string, keyLength int, tokenExpiration float64) *Game

Constructor.

func (*Game) Bench

func (g *Game) Bench(p *Player) error

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

func (g *Game) CheckTokenEquality(token string) error

Called whenever a game is looked up SocketServer.GetGame. It only checks for equality and not expiration because an already logged in player may still be sending requests to the socket server after the game has expired, which is legal. There needs to be a way to differentiate between a logged in user and one that is trying to log in after the game has expired, so breaking these token checks into there respective parts makes sense and accomplishes this goal. See Game.CheckTokenExpiration for more information.

func (*Game) CheckTokenExpiration

func (g *Game) CheckTokenExpiration() error

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

func (g *Game) GetPlayer(v interface{}) (*Player, error)

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

func (g *Game) HasPlayer(name string) (*Player, bool)

func (*Game) Unbench

func (g *Game) Unbench(p *Player) error

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

func (g *Game) UpdatePlayerScore(socket *websocket.Conn, points int) (int, error)

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

type PlayerScore struct {
	Name  string
	Score int
}

This is currently for an admin to get a quick view of the game state.

type Scoreboard

type Scoreboard []*PlayerScore

type ServerMessage

type ServerMessage struct {
	Type string      `json:"type,omitempty"`
	Data interface{} `json:"data,omitempty"`
}

This is marshaled to the browser client. See SocketServer.Publish.

type Socket

type Socket struct {
	Protocol string
	Domain   string
	Port     int
}

type SocketServer

type SocketServer struct {
	Location URI
	Games    map[string]*Game
	Tpl      *template.Template
}

A socket server instance is set up to handle multiple (concurrent) games.

func NewSocketServer

func NewSocketServer(uri URI) *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

func (s *SocketServer) GetPlayerBySocket(socket *websocket.Conn) (*Player, *Game, error)

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

func (s *SocketServer) KillHandler(w http.ResponseWriter, r *http.Request)

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)

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)

type URI

type URI struct {
	Sock Socket
	Path string
}

func (URI) String

func (u URI) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL