trivial

package
v0.0.0-...-0505374 Latest Latest
Warning

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

Go to latest
Published: Nov 20, 2024 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package trivialpoursuit implements a backend for a multi player trivial poursuit game, where questions are (short) maths questions.

Package trivial implements a game controller for one group of players, handling concurrency. It is meant to be used by a server with websocket connections for the players, but is actually network agnostic.

Index

Constants

View Source
const (
	AnswerClKind       = "Answer"
	ClientMoveClKind   = "ClientMove"
	DiceClickedClKind  = "DiceClicked"
	PingClKind         = "Ping"
	WantNextTurnClKind = "WantNextTurn"
)
View Source
const (
	DiceThrowSeKind                    = "DiceThrow"
	GameEndSeKind                      = "GameEnd"
	GameStartSeKind                    = "GameStart"
	GameTerminatedSeKind               = "GameTerminated"
	LobbyUpdateSeKind                  = "LobbyUpdate"
	MoveSeKind                         = "Move"
	PlayerAnswerResultsSeKind          = "PlayerAnswerResults"
	PlayerJoinSeKind                   = "PlayerJoin"
	PlayerLeftSeKind                   = "PlayerLeft"
	PlayerReconnectedSeKind            = "PlayerReconnected"
	PlayerTurnSeKind                   = "PlayerTurn"
	PlayersStillInQuestionResultSeKind = "PlayersStillInQuestionResult"
	PossibleMovesSeKind                = "PossibleMoves"
	ShowQuestionSeKind                 = "ShowQuestion"
)
View Source
const NbCategories = int(nbCategories)

NbCategories is the number of categories of question

Variables

View Source
var (
	WarningLogger  = log.New(os.Stdout, "tv-game:ERROR: ", 0)
	ProgressLogger = log.New(os.Stdout, "tv-game:INFO : ", 0)
)
View Source
var (
	// Board is the Trivial-Poursuit board game shape.
	Board = board{
		0:  {1: true, nbSquares - 1: true},
		1:  {0: true, 2: true},
		2:  {1: true, 3: true},
		3:  {2: true, 4: true, nbSquares - 3: true},
		4:  {3: true, 5: true},
		5:  {4: true, 6: true},
		6:  {5: true, 7: true},
		7:  {6: true, 8: true},
		8:  {7: true, 9: true},
		9:  {8: true, 10: true, nbSquares - 2: true},
		10: {9: true, 11: true},
		11: {10: true, 12: true},
		12: {11: true, 13: true},
		13: {12: true, 14: true},
		14: {13: true, 3: true},
		15: {16: true, 9: true},
		16: {15: true, 0: true},
	}
)
View Source
var ErrGameStarted = errors.New("game already started")

ErrGameStarted is returned from `Join` when the game has already started

View Source
var GameStartDelay = time.Second // reduced in tests to avoid latency

Functions

This section is empty.

Types

type Answer

type Answer struct {
	Answer client.QuestionAnswersIn
}

the proposition of a client to a question

type Categorie

type Categorie uint8

a Categorie of questions, represented by a color

const (
	Purple Categorie = iota // purple
	Green                   // green
	Orange                  // orange
	Yellow                  // yellow
	Blue                    // blue

)

type ClientEvent

type ClientEvent struct {
	Event  ClientEventITF // as send by the client
	Player PlayerID       // filled by the server
}

ClientEvent is a game event send by a known player

type ClientEventITF

type ClientEventITF interface {
	// contains filtered or unexported methods
}

ClientEventITF is the common interface for events send by a student client to the game server

type ClientEventITFWrapper

type ClientEventITFWrapper struct {
	Data ClientEventITF
}

ClientEventITFWrapper may be used as replacements for ClientEventITF when working with JSON

func (ClientEventITFWrapper) MarshalJSON

func (item ClientEventITFWrapper) MarshalJSON() ([]byte, error)

func (*ClientEventITFWrapper) UnmarshalJSON

func (out *ClientEventITFWrapper) UnmarshalJSON(src []byte) error

type ClientMove

type ClientMove Move

type Connection

type Connection interface {
	WriteJSON(v interface{}) error
}

Connection abstracts away the network technology used to communicate back to the client `WriteJSON` will be called from the event goroutine started by `Room.Listen`, so that implementations should support one concurrent write, as it is the case for gorilla/websocket.Connection

type DiceClicked

type DiceClicked struct{}

DiceClicked is emitted when the current player throws the dice

type DiceThrow

type DiceThrow struct {
	Face uint8
}

DiceThrow represents the result obtained when throwing a dice

type Events

type Events []ServerEvent

func (Events) MarshalJSON

func (list Events) MarshalJSON() ([]byte, error)

func (*Events) UnmarshalJSON

func (list *Events) UnmarshalJSON(data []byte) error

type GameEnd

type GameEnd struct {
	QuestionDecrassageIds map[serial][]editor.IdQuestion // player->questions
	Winners               []serial
	WinnerNames           []string
	Advances              map[serial]events.EventNotification
}

GameEnd is emitted when at least one player has won

type GameStart

type GameStart struct{}

type GameState

type GameState struct {
	Players    map[serial]PlayerStatus // per-player advance
	PlayerTurn serial                  // the player currently playing (choosing where to move)
	PawnTile   int                     // position of the pawn
}

GameState represents an on-going game.

type GameTerminated

type GameTerminated struct{}

GameTerminated is emitted when the game is manually terminated by the teacher

type LaunchStrategy

type LaunchStrategy struct {
	// If manual is [true], the game must be started
	// with [Room.StartGame]
	Manual bool

	// Max is the required number of players to start
	// a game in auto mode.
	// It is 0 in manual mode, > 0  in auto mode
	Max int
}

func (LaunchStrategy) String

func (ls LaunchStrategy) String() string

type LobbyUpdate

type LobbyUpdate struct {
	PlayerPseudos map[serial]string // the new players in the lobby
	Pseudo        string
	ID            serial         // the player who joined or left
	IsJoining     bool           // false for leaving
	PlayerRanks   map[serial]int // Added in v1.8
}

type Move

type Move struct {
	// the tiles to go through to animate the move
	// (only valid when send by the server)
	Path []int
	Tile int
}

Move is emitted when a player choose to Move the pawn

type Options

type Options struct {
	// QuestionPool is the list of the question
	// being asked, for each category
	Questions QuestionPool

	Launch LaunchStrategy

	// QuestionTimeout is the time limit for one question
	QuestionTimeout time.Duration

	ShowDecrassage bool

	// Every player start with [StartNbSuccess] success, which
	// should be zero in regular use, but may be higher for
	// testing purposes.
	StartNbSuccess int
}

Options is the configuration of one game. All fields are required.

type Ping

type Ping struct {
	Info string
}

Ping is used to maintain the client connection openned

type Player

type Player struct {
	ID PlayerID

	// Pseudo is the display name of each player,
	// which may change during a game (upon deconnection/reconnection)
	Pseudo string

	// PseudoSuffix is added to [Pseudo] when two players
	// have the same pseudo
	PseudoSuffix string

	// Isyro global rank for registrer players, or 0
	Rank int
}

Player represents one player.

type PlayerAnswerResults

type PlayerAnswerResults struct {
	Categorie Categorie
	Results   map[serial]playerAnswerResult
	Advances  map[serial]events.EventNotification
}

PlayerAnswerResults indicates if the players have answered correctly to the current question

type PlayerID

type PlayerID string

PlayerID is a unique identifier of each player, usually generated at the first connection. It is used to handle reconnection and external monitoring of the players

type PlayerJoin

type PlayerJoin struct {
	Player serial
}

PlayerJoin is only emitted to the actual player who join the game

type PlayerLeft

type PlayerLeft struct {
	Player serial
}

type PlayerReconnected

type PlayerReconnected struct {
	ID     serial
	Pseudo string
}

type PlayerStatus

type PlayerStatus struct {
	Name    string
	Review  QuestionReview
	Success Success
	// Has the player disconnect ?
	IsInactive bool
	Rank       int // added in v1.9
}

PlayerStatus exposes the information about one player

type PlayerTurn

type PlayerTurn struct {
	PlayerName string
	Player     serial
}

PlayerTurn is emitted at the start of a player

type PlayersStillInQuestionResult

type PlayersStillInQuestionResult struct {
	Players     []serial
	PlayerNames []string
}

PlayersStillInQuestionResult is emitted when some players are still in the [pQuestionResult] step

type PossibleMoves

type PossibleMoves struct {
	PlayerName string
	Tiles      []int  // the tile indices where the current player may move
	Player     serial // the player allowed to play
}

PossibleMoves is emitted after a diceThrow

type QR

type QR struct {
	IdQuestion editor.IdQuestion
	Success    bool
}

type QuestionContent

type QuestionContent struct {
	ID        editor.IdQuestion          // the origin
	Question  questions.QuestionInstance // the instantiated version
	Vars      expression.Vars            // the corresponding parameters
	Categorie Categorie                  // the origin
}

QuestionContent stores the ID of the question and its instance

type QuestionPool

type QuestionPool [NbCategories]WeigthedQuestions

type QuestionReview

type QuestionReview struct {
	QuestionHistory []QR
	// Ids of question the player wants to mark for further work
	MarkedQuestions []editor.IdQuestion
}

QuestionReview stores the results of one player against the questions asked during the game

type Replay

type Replay struct {
	QuestionHistory map[Player]QuestionReview
	ID              RoomID
}

Replay exposes some information to be persisted after the game end, such as the successes of the players

type Room

type Room struct {
	// ID is the readonly ID for this game.
	ID RoomID

	// Terminate is used to cleanly exit the game,
	// noticing clients and exiting the main goroutine.
	// It is however not considered as a normal exit,
	// so that the `Replay` is not emitted.
	Terminate chan bool

	// Leave is used when the player leave the game
	// (either on purpose or when its connection breaks)
	// For started games, the player is only set inactive,
	// whereas for waiting (in lobby) games, the player is totaly removed.
	Leave chan PlayerID

	// Event is used when a client send an event
	Event chan ClientEvent
	// contains filtered or unexported fields
}

Room is the game host, and the main entry point of a game. All exported methods are safe for concurrent use; events are send on the exposed channel fields.

func NewRoom

func NewRoom(ID RoomID, options Options, successHandler SuccessHandler) *Room

func (*Room) HasStarted

func (r *Room) HasStarted() bool

HasStarted locks and returns `true` if the game has already started

func (*Room) Join

func (r *Room) Join(player Player, connection Connection) error

Join should be used on a new connection, on one the of the following cases:

  • totally fresh connection
  • reconnection in an already started game

It is safe for concurrent uses. It returns an error for instance if the game has already started.

func (*Room) Listen

func (r *Room) Listen(ctx context.Context) (replay Replay, naturalEnding bool)

Listen starts the main game loop, listening on the game channels and blocking. Note that it does not start the game itself : the game state is initially in the lobby. It returns `true` when the game is over, or `false` when it was manually terminated. Care should be taken to make sure no more events are send on the channels when this method has returned.

func (*Room) NbActivePlayers

func (r *Room) NbActivePlayers() int

NbActivePlayers locks and returns the number of players currently connected.

func (*Room) Options

func (r *Room) Options() Options

Options returns the (readonly) configuration used by the game.

func (*Room) StartGame

func (r *Room) StartGame() error

StartGame launches the game, returning an error if the game is in auto mode, or if no players are in the game yet.

It is safe for concurrent use.

func (*Room) Summary

func (r *Room) Summary() Summary

Summary locks and returns the current game summary.

type RoomID

type RoomID string

RoomID is the public, full identifier of a game room, whose extact form varies according to the launch mode of the game. It is not used internally by this package but associated to every room object, and will be used by consuming packages.

type RoomSize

type RoomSize struct {
	Current int
	Max     int // 0 in manual mode, > 0 in auto mode
}

type ServerEvent

type ServerEvent interface {
	// contains filtered or unexported methods
}

ServerEvent is an action (created by the server) advancing the game or requiring to update the UI

type ServerEventWrapper

type ServerEventWrapper struct {
	Data ServerEvent
}

ServerEventWrapper may be used as replacements for ServerEvent when working with JSON

func (ServerEventWrapper) MarshalJSON

func (item ServerEventWrapper) MarshalJSON() ([]byte, error)

func (*ServerEventWrapper) UnmarshalJSON

func (out *ServerEventWrapper) UnmarshalJSON(src []byte) error

type ShowQuestion

type ShowQuestion struct {
	TimeoutSeconds int
	Categorie      Categorie
	ID             editor.IdQuestion // to facilitate the tracking of the question results
	Question       client.Question   // the actual question
}

ShowQuestion is emitted when a player should answer a question

type StateUpdate

type StateUpdate struct {
	Events Events
	State  GameState
}

StateUpdate describes a list of events yielding a new game state. Clients should animate the events and update the state.

func (StateUpdate) String

func (su StateUpdate) String() string

type Success

type Success [NbCategories]bool

Success are the categories completed by a player

type SuccessHandler

type SuccessHandler interface {
	OnQuestion(player PlayerID, correct, hasStreak3 bool) events.EventNotification
	OnWin(player PlayerID) events.EventNotification
}

SuccessHandler reacts to students acheiving global success.

It will typically be implemented with a [*sql.DB]

type Summary

type Summary struct {
	PlayerTurn *Player // nil before game start
	// Successes does not contains disconnected players
	Successes      map[string]Success
	ID             RoomID
	RoomSize       RoomSize        // Number of players
	LatestQuestion QuestionContent // zero ID before the first question

	// During question phase, it is the list
	// of players still answering a question.
	// After a question, is is the list of players still not ready for the next turn.
	// Empty otherwise
	InQuestionStudents []string
}

Summary provides an high level overview of the game, and may be emitted back to the teacher monitor.

type WantNextTurn

type WantNextTurn struct {
	// MarkQuestion is true if the player wants to
	// keep the question for following trainings
	MarkQuestion bool
}

WantNextTurn is emitted when a player is done looking at the question answer panel

type WeigthedQuestions

type WeigthedQuestions struct {
	Questions []editor.Question
	Weights   []float64 // same length as `Questions`
}

Jump to

Keyboard shortcuts

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