summaryrefslogtreecommitdiff
path: root/swiftstory
diff options
context:
space:
mode:
Diffstat (limited to 'swiftstory')
-rw-r--r--swiftstory/board.py9
-rw-r--r--swiftstory/cards.py4
-rw-r--r--swiftstory/client.py11
-rw-r--r--swiftstory/exception.py11
-rw-r--r--swiftstory/game.py15
-rw-r--r--swiftstory/game_manager.py9
-rw-r--r--swiftstory/interface/ws.py5
-rw-r--r--swiftstory/player.py7
-rw-r--r--swiftstory/status.py4
9 files changed, 69 insertions, 6 deletions
diff --git a/swiftstory/board.py b/swiftstory/board.py
index 31ddd11..01082e4 100644
--- a/swiftstory/board.py
+++ b/swiftstory/board.py
@@ -1,3 +1,5 @@
+""" This module defines the Board class. """
+
import random
from typing import List, Optional, Tuple
@@ -9,6 +11,7 @@ class Board:
of cards '''
def __init__(self) -> None:
+ """ Initializer for the board. """
self.white_pick: List[Tuple[int, str]] = []
self.black_pick: List[Tuple[int, str]] = []
self.white_recycled: List[Tuple[int, str]] = []
@@ -19,6 +22,8 @@ class Board:
self.played_cards: List[Tuple[Tuple[int, str], Player]] = []
def reveal_next_black_card(self) -> None:
+ """ Fetch the next black card and reveal it. The current card (if any)
+ moves to the recycling heap. """
if self.current_black_card is not None:
self.black_recycled.append(self.current_black_card)
self.current_black_card = None
@@ -33,6 +38,7 @@ class Board:
self.current_black_card = self.black_pick.pop()
def pick_white_card(self) -> Tuple[int, str]:
+ """ Fetch and return the next white card. """
if not self.white_pick:
# If we have no more cards in the deck, we need to reform one using
# the cards that have been recycled.
@@ -43,12 +49,15 @@ class Board:
return self.white_pick.pop()
def play_card(self, player: Player, card: Tuple[int, str]) -> None:
+ """ Add a card to the played cards for this round. """
self.played_cards.append((card, player))
def shuffle_played_cards(self) -> None:
+ """ Shuffle the heap of played cards. """
random.shuffle(self.played_cards)
def recycle_played_cards(self) -> None:
+ """ Move the played cards to the recycling heap of white cards. """
self.white_recycled += [i[0] for i in self.played_cards]
self.played_cards = []
diff --git a/swiftstory/cards.py b/swiftstory/cards.py
index 7f28919..3c11f49 100644
--- a/swiftstory/cards.py
+++ b/swiftstory/cards.py
@@ -1,3 +1,5 @@
+""" Module that defines helpers to read cards from the filesystem. """
+
import json
import os
from typing import List
@@ -6,6 +8,8 @@ from pkg_resources import resource_stream
class Cards:
+ """ Dummy class that provides helper functions to retrieve the cards from
+ the FS. """
@staticmethod
def get_white_cards(lang: str) -> List[str]:
''' Read the file containing the white cards and return a list of cards '''
diff --git a/swiftstory/client.py b/swiftstory/client.py
index 28fd6c0..cd5e82a 100644
--- a/swiftstory/client.py
+++ b/swiftstory/client.py
@@ -1,3 +1,5 @@
+""" Module that defines the client class. """
+
import asyncio
import logging
from typing import Optional
@@ -23,6 +25,7 @@ class Client:
self.player: Optional[Player] = None
def join_game(self, game_name: str, lang: Optional[str]) -> str:
+ """ Attempt to join a game and return an answer. """
if self.game is not None:
raise WrongAction('You are already in a game')
@@ -42,6 +45,7 @@ class Client:
return status
def play_white_card(self, card_id: int) -> str:
+ """ Play a card and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -49,6 +53,7 @@ class Client:
return self.game.try_play_card(self.player, card_id)
def pick_black_card(self) -> str:
+ """ Pick a black card (and become the judge) and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -56,6 +61,7 @@ class Client:
return self.game.try_become_judge(self.player)
def collect_cards(self) -> str:
+ """ Collect the played cards and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -63,6 +69,7 @@ class Client:
return self.game.try_collect_cards(self.player)
def designate_card(self, card_id: Optional[int]) -> str:
+ """ Designate the best card and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -70,6 +77,7 @@ class Client:
return self.game.try_designate_card(self.player, card_id)
def view_player_cards(self) -> str:
+ """ View our own cards and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -77,6 +85,7 @@ class Client:
return self.game.try_view_player_cards(self.player)
def view_played_cards(self) -> str:
+ """ View the cards played at this round and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -84,6 +93,7 @@ class Client:
return self.game.try_view_played_cards(self.player)
def view_black_card(self) -> str:
+ """ View the current black card and return an answer. """
if self.game is None:
raise WrongAction('You have to join a game first')
if self.player is None:
@@ -104,6 +114,7 @@ class Client:
asyncio.create_task(f())
def disconnect(self) -> None:
+ """ Detach from the player. """
if self.player is not None:
if self.game is None:
raise ValueError("Disconnect from inexistent game.")
diff --git a/swiftstory/exception.py b/swiftstory/exception.py
index 764289f..ad7a894 100644
--- a/swiftstory/exception.py
+++ b/swiftstory/exception.py
@@ -1,9 +1,14 @@
+""" Define a few exceptions types to be used. """
+
class WrongAction(Exception):
- pass
+ """ Exception to be raised when a player performs an action that is not
+ permitted. """
class UnsupportedLanguage(Exception):
- pass
+ """ Exception to be raised when trying to join a game in a language that is
+ not supported. """
+
class JoinError(Exception):
- pass
+ """ Exception to be raised when a game/room cannot be joined. """
diff --git a/swiftstory/game.py b/swiftstory/game.py
index c46df4b..b2ec493 100644
--- a/swiftstory/game.py
+++ b/swiftstory/game.py
@@ -1,3 +1,5 @@
+""" Module that defines the main component of the game. """
+
from enum import Enum, auto
import random
from typing import List, Optional, Tuple
@@ -9,12 +11,14 @@ from swiftstory.status import error, success
class GameState(Enum):
+ """ Enumeration of the different game states. """
WAITING_NEW_JUDGE = auto(),
WAITING_COLLECTION = auto(),
WAITING_DESIGNATION = auto(),
class Game:
+ """ Represent a game, including the board, players and state. """
def __init__(self, white_desc: List[str], black_desc: List[str]) -> None:
self.state = GameState.WAITING_NEW_JUDGE
@@ -31,6 +35,7 @@ class Game:
random.shuffle(self.board.black_pick)
def try_join(self, player: Player) -> str:
+ """ Attempt to join the game. Return an answer. """
if len(self.players) >= 10:
raise JoinError('too many players in this game')
@@ -64,6 +69,7 @@ class Game:
def try_become_judge(self, player: Player) -> str:
+ """ Attempt to become the judge of the game. Return an answer. """
if self.state is not GameState.WAITING_NEW_JUDGE:
# TODO what if the judge has quit ?
raise WrongAction('Someone is judge already')
@@ -81,6 +87,7 @@ class Game:
def try_play_card(self, player: Player, card_id: int) -> str:
+ """ Attempt to play a card. Return an answer. """
if self.state is not GameState.WAITING_COLLECTION:
raise WrongAction('Who asked you to play now ?!')
@@ -106,6 +113,8 @@ class Game:
def try_collect_cards(self, player: Player) -> str:
+ """ Attempt to collect the cards play in the current round. Return an
+ answer. """
if self.state is not GameState.WAITING_COLLECTION:
raise WrongAction("Do you think it's the moment for collection !?")
@@ -125,6 +134,7 @@ class Game:
def try_designate_card(self, player: Player, card_id: Optional[int]) -> str:
+ """ Attempt to designate the best card. Return an answer. """
if self.state is not GameState.WAITING_DESIGNATION:
raise WrongAction('Not now, moron !')
@@ -177,15 +187,19 @@ class Game:
return move_on()
def try_view_player_cards(self, player: Player) -> str:
+ """ Attempt to view the cards of the given player. Return an answer. """
return success([(idx, desc) for idx, (_, desc) in player.cards.items()])
def try_view_played_cards(self, player: Player) -> str:
+ """ Attempt to view the cards that have been played. Return an answer.
+ """
if self.state is not GameState.WAITING_DESIGNATION:
raise WrongAction('Not now, moron !')
return success([desc for (_, desc), _ in self.board.played_cards])
def try_view_black_card(self, player: Player) -> str:
+ """ Attempt to view the black card. Return an answer. """
card = self.board.current_black_card
if card is not None:
@@ -194,6 +208,7 @@ class Game:
raise WrongAction('The black card has not been revealed yet')
def disconnect(self, player: Player) -> None:
+ """ Deatch a player from the game. """
if self.judge is player:
self.judge = None
diff --git a/swiftstory/game_manager.py b/swiftstory/game_manager.py
index 56279a6..aa951f5 100644
--- a/swiftstory/game_manager.py
+++ b/swiftstory/game_manager.py
@@ -1,3 +1,6 @@
+""" Module defining a class to store the games/rooms in the different
+languages. """
+
from dataclasses import dataclass
import logging
from typing import Dict, List
@@ -10,7 +13,7 @@ from swiftstory.cards import Cards
class NoSuchGameError(Exception):
- """ Exception to be raised when no game is found matching the criterias.
+ """ Exception to be raised when no game is found matching the criterion.
"""
def __init__(self, message: str = "", game_name: str = "", lang: str = "") -> None:
self.game_name = game_name
@@ -20,14 +23,14 @@ class NoSuchGameError(Exception):
@dataclass
class LangContainer:
- """ Container for game ojects in a given language. """
+ """ Container for game objects in a given language. """
black_cards: List[str]
white_cards: List[str]
games: Dict[str, Game]
class GameManager:
-
+ """ Store the different rooms/games of the different languages. """
def __init__(self) -> None:
self.lang_containers: Dict[str, LangContainer] = {}
diff --git a/swiftstory/interface/ws.py b/swiftstory/interface/ws.py
index a86c730..082ed1a 100644
--- a/swiftstory/interface/ws.py
+++ b/swiftstory/interface/ws.py
@@ -1,3 +1,6 @@
+""" Module that defines the interface (using WebSockets) between the GUI and
+the game itself. """
+
import contextlib
import json
import logging
@@ -18,6 +21,7 @@ class WebsocketsInterface:
self.game_manager = game_manager
async def connection_handler(self, websocket: WebSocketServerProtocol, path: str) -> None:
+ """ Coroutine that handles one websocket connection. """
client = Client(websocket, self.game_manager)
with contextlib.suppress(websockets.exceptions.ConnectionClosed):
@@ -27,6 +31,7 @@ class WebsocketsInterface:
client.disconnect()
def message_received_handler(self, client: Client, message: Union[bytes, str]) -> str:
+ """ Handle a message and return an answer. """
def join_game() -> str:
try:
game_name = json_msg['game_name']
diff --git a/swiftstory/player.py b/swiftstory/player.py
index 7243585..2df6882 100644
--- a/swiftstory/player.py
+++ b/swiftstory/player.py
@@ -1,9 +1,12 @@
+""" Module defining the player class. """
+
import asyncio
import json
from typing import Any, Dict, Tuple
class Player:
+ """ Represent a player. """
def __init__(self) -> None:
self.cards: Dict[int, Tuple[int, str]] = {}
self.next_idx = 0
@@ -16,9 +19,11 @@ class Player:
self.notifications: asyncio.Queue = asyncio.Queue()
def pop_card(self, card_id: int) -> Tuple[int, str]:
+ """ Take and return the card at index card_id. """
return self.cards.pop(card_id)
def inc_score(self) -> None:
+ """ Increase the score by one. """
self.score += 1
self.register_notification({
'op': 'updated_score',
@@ -26,11 +31,13 @@ class Player:
})
def receive_card(self, card: Tuple[int, str]) -> int:
+ """ Receive a card and return its index. """
self.cards[self.next_idx] = card
self.next_idx += 1
return self.next_idx - 1
def register_notification(self, obj: Any) -> None:
+ """ Register a notification to be picked up by the client. """
message = json.dumps({'type': 'notification', 'content': obj})
self.notifications.put_nowait(message)
diff --git a/swiftstory/status.py b/swiftstory/status.py
index d794580..a35f66a 100644
--- a/swiftstory/status.py
+++ b/swiftstory/status.py
@@ -1,9 +1,13 @@
+""" Module defining helpers to craft answers to be sent to clients. """
+
from typing import Any
import json
def error(msg: str, code: int = 255) -> str:
+ """ Generate an error. """
return json.dumps({'type': 'response', 'content': {'status': code, 'info': msg}})
def success(obj: Any) -> str:
+ """ Generate a success message. """
return json.dumps({'type': 'response', 'content': {'status': 0, 'result': obj}})