Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: next rubber #258

Merged
merged 8 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 48 additions & 10 deletions tests/whist_core/session/test_table.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from unittest.mock import patch

from tests.whist_core.base_test_case import BaseTestCase
from whist_core.error.table_error import TeamFullError, TableFullError, TableNotReadyError, \
TableNotStartedError, PlayerNotJoinedError, TableSettingsError
from whist_core.game.errors import RubberNotDoneError
from whist_core.game.rubber import Rubber
from whist_core.session.matcher import RandomMatcher, RoundRobinMatcher
from whist_core.session.table import Table
Expand Down Expand Up @@ -68,36 +71,71 @@ def test_join_full_table(self):

def test_conversion(self):
self.table.join(self.player)
table_dict = self.table.dict()
table_dict = self.table.dict(exclude={'matcher'})
table = Table(**table_dict)
self.assertEqual(self.table, table)

def test_start_random(self):
table = Table(name='test table', min_player=1, max_player=4, matcher=RandomMatcher())
second_player = Player(username='miles', rating=3000)
self.table.join(self.player)
self.table.join(second_player)
self.table.player_ready(self.player)
self.table.player_ready(second_player)
self.table.start(RandomMatcher)
self.assertTrue(self.table.started)
self.assertIsInstance(self.table.current_rubber, Rubber)
table.join(self.player)
table.join(second_player)
table.player_ready(self.player)
table.player_ready(second_player)
table.start()
self.assertTrue(table.started)
self.assertIsInstance(table.current_rubber, Rubber)
self.assertTrue(isinstance(table.matcher, RandomMatcher))

def test_start_robin(self):
second_player = Player(username='miles', rating=3000)
self.table.join(self.player)
self.table.join(second_player)
self.table.player_ready(self.player)
self.table.player_ready(second_player)
self.table.start(RoundRobinMatcher)
self.table.start()
self.assertTrue(self.table.started)
self.assertIsInstance(self.table.current_rubber, Rubber)
self.assertTrue(isinstance(self.table.matcher, RoundRobinMatcher))

def test_not_ready_start(self):
self.table.join(self.player)
with self.assertRaises(TableNotReadyError):
self.table.start(RandomMatcher)
self.table.start()
self.assertFalse(self.table.started)

def test_rubber_without_start(self):
with self.assertRaises(TableNotStartedError):
_ = self.table.current_rubber

def test_next_rubber(self):
second_player = Player(username='miles', rating=3000)
self.table.join(self.player)
self.table.join(second_player)
self.table.player_ready(self.player)
self.table.player_ready(second_player)
self.table.start()
with patch('whist_core.game.rubber.Rubber.done', return_value=True):
self.table.next_rubber()
self.assertEqual(2, len(self.table.rubbers))

def test_next_rubber_not_done(self):
second_player = Player(username='miles', rating=3000)
self.table.join(self.player)
self.table.join(second_player)
self.table.player_ready(self.player)
self.table.player_ready(second_player)
self.table.start()
with self.assertRaises(RubberNotDoneError):
self.table.next_rubber()
self.assertEqual(1, len(self.table.rubbers))

def test_next_rubber_first(self):
second_player = Player(username='miles', rating=3000)
self.table.join(self.player)
self.table.join(second_player)
self.table.player_ready(self.player)
self.table.player_ready(second_player)
with self.assertRaises(TableNotStartedError):
self.table.next_rubber()
self.assertEqual(0, len(self.table.rubbers))
6 changes: 6 additions & 0 deletions whist_core/game/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ class NoTrumpSelectedError(Exception):
"""


class RubberNotDoneError(Exception):
"""
Raised if the current rubber is not done, but action requested requires it to be done.
"""


class TrickDoneError(Exception):
"""
Raised when the trick is already done.
Expand Down
4 changes: 3 additions & 1 deletion whist_core/session/matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import abc
import random

from pydantic import BaseModel

from whist_core.error.matcher_error import NotEnoughPlayersError
from whist_core.scoring.team import Team
from whist_core.session.userlist import UserList


# pylint: disable=too-few-public-methods
class Matcher(abc.ABC):
class Matcher(abc.ABC, BaseModel):
"""
Abstrakt class for player to teams matching.
"""
Expand Down
37 changes: 28 additions & 9 deletions whist_core/session/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

from whist_core.error.table_error import TableFullError, TeamFullError, TableNotReadyError, \
TableNotStartedError, TableSettingsError
from whist_core.game.errors import RubberNotDoneError
from whist_core.game.rubber import Rubber
from whist_core.session.matcher import Matcher
from whist_core.session.matcher import Matcher, RoundRobinMatcher
from whist_core.session.session import Session
from whist_core.user.player import Player

Expand All @@ -18,6 +19,7 @@ class Table(Session):
team_size: int = 2
started: bool = False
rubbers: list[Rubber] = []
matcher: Matcher = RoundRobinMatcher()

# pylint: disable=no-self-argument
@root_validator(pre=True)
Expand Down Expand Up @@ -67,20 +69,27 @@ def current_rubber(self) -> Rubber:
raise TableNotStartedError()
return self.rubbers[-1]

def start(self, matcher: Matcher) -> None:
def next_rubber(self) -> Rubber:
"""
Creates the next rubber. In order to create the first rubber use 'Table.start()'.
:return: the new rubber
"""
if len(self.rubbers) == 0:
raise TableNotStartedError()
if self.rubbers[-1].done:
self.rubbers.append(self._create_rubber())
else:
raise RubberNotDoneError()
return self.current_rubber

def start(self) -> None:
"""
Starts the table, but will check if every player is ready first.
"""
if not self.ready:
raise TableNotReadyError()

team_numbers = 2
players_available_per_team = int(len(self.users) / team_numbers)
teams = matcher.distribute(num_teams=team_numbers,
team_size=min(players_available_per_team, self.team_size),
users=self.users)
rubber = Rubber(teams=teams)
self.rubbers.append(rubber)
self.rubbers.append(self._create_rubber())
self.started = True

def join(self, player: Player) -> None:
Expand Down Expand Up @@ -142,3 +151,13 @@ def player_unready(self, player) -> None:
:rtype: None
"""
self.users.player_unready(player)

def _create_rubber(self):
team_numbers = 2
players_available_per_team = int(len(self.users) / team_numbers)
teams = self.matcher.distribute(num_teams=team_numbers,
team_size=min(players_available_per_team,
self.team_size),
users=self.users)
rubber = Rubber(teams=teams)
return rubber