apologiesserver.interface

Definition of the public interface for the server.

Both requests (message sent from a client to the server) and events (published from the server to one or more clients) can be serialized and deserialized to and from JSON. However, we apply much tighter validation rules on the context associated with requests, since the input is untrusted. We assume that the unit tests and the Python type validations imposed by MyPy give us everything we need for events that are only built internally.

The file docs/design.rst includes a detailed discussion of each request and event.

Module Contents

class apologiesserver.interface.Visibility(*args, **kwds)

Bases: enum.Enum

Visibility for advertised games.

PUBLIC = 'Public'
PRIVATE = 'Private'
class apologiesserver.interface.CancelledReason(*args, **kwds)

Bases: enum.Enum

Reasons a game can be cancelled.

CANCELLED = 'Game was cancelled by advertiser'
NOT_VIABLE = 'Game is no longer viable.'
INACTIVE = 'The game was idle too long and was marked inactive'
SHUTDOWN = 'Game was cancelled due to system shutdown'
class apologiesserver.interface.PlayerType(*args, **kwds)

Bases: enum.Enum

Types of players.

HUMAN = 'Human'
PROGRAMMATIC = 'Programmatic'
class apologiesserver.interface.PlayerState(*args, **kwds)

Bases: enum.Enum

A player’s game state.

WAITING = 'Waiting'
JOINED = 'Joined'
PLAYING = 'Playing'
FINISHED = 'Finished'
QUIT = 'Quit'
DISCONNECTED = 'Disconnected'
class apologiesserver.interface.ConnectionState(*args, **kwds)

Bases: enum.Enum

A player’s connection state.

CONNECTED = 'Connected'
DISCONNECTED = 'Disconnected'
class apologiesserver.interface.ActivityState(*args, **kwds)

Bases: enum.Enum

A player’s activity state.

ACTIVE = 'Active'
IDLE = 'Idle'
INACTIVE = 'Inactive'
class apologiesserver.interface.GameState(*args, **kwds)

Bases: enum.Enum

A game’s state.

ADVERTISED = 'Advertised'
PLAYING = 'Playing'
COMPLETED = 'Completed'
CANCELLED = 'Cancelled'
class apologiesserver.interface.FailureReason(*args, **kwds)

Bases: enum.Enum

Failure reasons advertised to clients.

INVALID_REQUEST = 'Invalid request'
DUPLICATE_USER = 'Handle is already in use'
INVALID_AUTH = 'Missing or invalid authorization header'
WEBSOCKET_LIMIT = 'Connection limit reached; try again later'
USER_LIMIT = 'System user limit reached; try again later'
GAME_LIMIT = 'System game limit reached; try again later'
INVALID_PLAYER = 'Unknown or invalid player'
INVALID_GAME = 'Unknown or invalid game'
NOT_PLAYING = 'Player is not playing a game'
NOT_ADVERTISER = 'Player did not advertise this game'
ALREADY_PLAYING = 'Player is already playing a game'
NO_MOVE_PENDING = 'No move is pending for this player'
ILLEGAL_MOVE = 'The chosen move is not legal'
ADVERTISER_MAY_NOT_QUIT = 'Advertiser may not quit a game (cancel instead)'
INTERNAL_ERROR = 'Internal error'
class apologiesserver.interface.MessageType(*args, **kwds)

Bases: enum.Enum

Enumeration of all message types, including received events and published requests.

REGISTER_PLAYER = 'Register Player'
REREGISTER_PLAYER = 'Reregister Player'
UNREGISTER_PLAYER = 'Unregister Player'
LIST_PLAYERS = 'List Players'
ADVERTISE_GAME = 'Advertise Game'
LIST_AVAILABLE_GAMES = 'List Available'
JOIN_GAME = 'Join Game'
QUIT_GAME = 'Quit Game'
START_GAME = 'Start Game'
CANCEL_GAME = 'Cancel Game'
EXECUTE_MOVE = 'Execute Move'
OPTIMAL_MOVE = 'Optimal Move'
RETRIEVE_GAME_STATE = 'Retrieve Game State'
SEND_MESSAGE = 'Send Message'
SERVER_SHUTDOWN = 'Server Shutdown'
REQUEST_FAILED = 'Request Failed'
REGISTERED_PLAYERS = 'Registered Players'
AVAILABLE_GAMES = 'Available Games'
PLAYER_REGISTERED = 'Player Registered'
PLAYER_UNREGISTERED = 'Player Unregistered'
WEBSOCKET_IDLE = 'Connection Idle'
WEBSOCKET_INACTIVE = 'Connection Inactive'
PLAYER_IDLE = 'Player Idle'
PLAYER_INACTIVE = 'Player Inactive'
PLAYER_MESSAGE_RECEIVED = 'Player Message Received'
GAME_ADVERTISED = 'Game Advertise'
GAME_INVITATION = 'Game Invitation'
GAME_JOINED = 'Game Joined'
GAME_STARTED = 'Game Started'
GAME_CANCELLED = 'Game Cancelled'
GAME_COMPLETED = 'Game Completed'
GAME_IDLE = 'Game Idle'
GAME_INACTIVE = 'Game Inactive'
GAME_PLAYER_QUIT = 'Game Player Quit'
GAME_PLAYER_CHANGE = 'Game Player Change'
GAME_STATE_CHANGE = 'Game State Change'
GAME_PLAYER_TURN = 'Game Player Turn'
exception apologiesserver.interface.ProcessingError

Bases: RuntimeError

Exception thrown when there is a general processing error.

reason: FailureReason
comment: str | None = None
handle: str | None = None
__repr__() str

Return repr(self).

__str__() str

Return str(self).

class apologiesserver.interface.GamePlayer

The public definition of a player within a game.

handle: str
player_color: apologies.PlayerColor | None
player_type: PlayerType
player_state: PlayerState
class apologiesserver.interface.RegisteredPlayer

The public definition of a player registered with the system.

handle: str
registration_date: arrow.Arrow
last_active_date: arrow.Arrow
connection_state: ConnectionState
activity_state: ActivityState
player_state: PlayerState
game_id: str | None
class apologiesserver.interface.AdvertisedGame

A game that has been advertised in the system.

game_id: str
name: str
mode: apologies.GameMode
advertiser_handle: str
players: int
available: int
visibility: Visibility
invited_handles: list[str]
class apologiesserver.interface.GameStatePawn

State of a pawn in a game.

color: apologies.PlayerColor
id: str
start: bool
home: bool
safe: int | None
square: int | None
static for_pawn(pawn: apologies.Pawn) GameStatePawn

Create a GameStatePawn based on apologies.game.Pawn.

static for_position(pawn: apologies.Pawn, position: apologies.Position) GameStatePawn

Create a GameStatePawn based on apologies.game.Pawn and apologies.gamePosition.

class apologiesserver.interface.GameStatePlayer

Player in a game, when describing the state of the board.

color: apologies.PlayerColor
turns: int
hand: list[apologies.CardType]
pawns: list[GameStatePawn]
static for_player(player: apologies.Player) GameStatePlayer

Create a GameStatePlayer based on apologies.game.Player.

class apologiesserver.interface.GameStateHistory

History for a game.

action: str
color: apologies.PlayerColor | None
card: apologies.CardType | None
timestamp: arrow.Arrow
static for_history(history: apologies.History) GameStateHistory
class apologiesserver.interface.GameAction

An action applied to a pawn in a game.

start: GameStatePawn
end: GameStatePawn
static for_action(action: apologies.Action) GameAction

Create a GamePlayerAction based on apologies.rules.Action.

class apologiesserver.interface.GameMove

A move that may be executed as a result of a player’s turn.

move_id: str
card: apologies.CardType
actions: list[GameAction]
side_effects: list[GameAction]
static for_move(move: apologies.Move) GameMove

Create a GameMove based on apologies.rules.Move.

class apologiesserver.interface.RegisterPlayerContext

Bases: Context

Context for a REGISTER_PLAYER request.

handle: str
class apologiesserver.interface.ReregisterPlayerContext

Bases: Context

Context for a REREGISTER_PLAYER request.

handle: str
class apologiesserver.interface.AdvertiseGameContext

Bases: Context

Context for an ADVERTISE_GAME request.

name: str
mode: apologies.GameMode
players: int
visibility: Visibility
invited_handles: list[str]
class apologiesserver.interface.JoinGameContext

Bases: Context

Context for a JOIN_GAME request.

game_id: str
class apologiesserver.interface.ExecuteMoveContext

Bases: Context

Context for an EXECUTE_MOVE request.

move_id: str
class apologiesserver.interface.SendMessageContext

Bases: Context

Context for an SEND_MESSAGE request.

message: str
recipient_handles: list[str]
class apologiesserver.interface.RequestFailedContext

Bases: Context

Context for a REQUEST_FAILED event.

reason: FailureReason
comment: str | None
handle: str | None = None
class apologiesserver.interface.RegisteredPlayersContext

Bases: Context

Context for a REGISTERED_PLAYERS event.

players: list[RegisteredPlayer]
class apologiesserver.interface.AvailableGamesContext

Bases: Context

Context for an AVAILABLE_GAMES event.

games: list[AdvertisedGame]
class apologiesserver.interface.PlayerRegisteredContext

Bases: Context

Context for a PLAYER_REGISTERED event.

handle: str
class apologiesserver.interface.PlayerUnregisteredContext

Bases: Context

Context for a PLAYER_UNREGISTERED event.

handle: str
class apologiesserver.interface.PlayerIdleContext

Bases: Context

Context for a PLAYER_IDLE event.

handle: str
class apologiesserver.interface.PlayerInactiveContext

Bases: Context

Context for a PLAYER_INACTIVE event.

handle: str
class apologiesserver.interface.PlayerMessageReceivedContext

Bases: Context

Context for a PLAYER_MESSAGE_RECEIVED event.

sender_handle: str
recipient_handles: list[str]
message: str
class apologiesserver.interface.GameAdvertisedContext

Bases: Context

Context for a GAME_ADVERTISED event.

game: AdvertisedGame
class apologiesserver.interface.GameInvitationContext

Bases: Context

Context for a GAME_INVITATION event.

game: AdvertisedGame
class apologiesserver.interface.GameJoinedContext

Bases: Context

Context for a GAME_JOINED event.

player_handle: str
game_id: str
name: str
mode: apologies.GameMode
advertiser_handle: str
class apologiesserver.interface.GameStartedContext

Bases: Context

Context for a GAME_STARTED event.

game_id: str
class apologiesserver.interface.GameCancelledContext

Bases: Context

Context for a GAME_CANCELLED event.

game_id: str
reason: CancelledReason
comment: str | None
class apologiesserver.interface.GameCompletedContext

Bases: Context

Context for a GAME_COMPLETED event.

game_id: str
winner: str
comment: str
class apologiesserver.interface.GameIdleContext

Bases: Context

Context for a GAME_IDLE event.

game_id: str
class apologiesserver.interface.GameInactiveContext

Bases: Context

Context for a GAME_INACTIVE event.

game_id: str
class apologiesserver.interface.GamePlayerQuitContext

Bases: Context

Context for a GAME_PLAYER_LEFT event.

handle: str
game_id: str
class apologiesserver.interface.GamePlayerChangeContext

Bases: Context

Context for a GAME_PLAYER_CHANGE event.

game_id: str
comment: str | None
players: list[GamePlayer]
class apologiesserver.interface.GameStateChangeContext

Bases: Context

Context for a GAME_STATE_CHANGE event.

game_id: str
recent_history: list[GameStateHistory]
player: GameStatePlayer
opponents: list[GameStatePlayer]
static for_context(game_id: str, view: apologies.PlayerView, history: list[apologies.History]) GameStateChangeContext

Create a GameStateChangeContext based on apologies.game.PlayerView.

class apologiesserver.interface.GamePlayerTurnContext

Bases: Context

Context for a GAME_PLAYER_TURN event.

handle: str
game_id: str
drawn_card: apologies.CardType | None
moves: dict[str, GameMove]
static for_moves(handle: str, game_id: str, moves: list[apologies.Move]) GamePlayerTurnContext

Create a GamePlayerTurnContext based on a sequence of apologies.rules.Move.

class apologiesserver.interface.Message

A message that is part of the public interface, either a client request or a published event.

message: MessageType
player_id: str | None
context: Any
to_json() str

Convert the request to JSON.

static for_json(data: str) Message

Create a request based on JSON data.