Beispiel #1
0
class Card(db.Model):
    '''Provide card object.'''

    # TODO join rank suit
    id = db.Column(db.Integer, primary_key=True)
    # id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
    rank = db.Column(db.String(1), unique=False, nullable=False)
    suit = db.Column(db.String(1), unique=False, nullable=False)

    ranks: tuple = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K',
                    'A')
    suits: tuple = ('C', 'D', 'H', 'S')

    def __init__(self, rank: str, suit: str) -> None:
        '''Initialize card.'''
        if rank in Card.ranks:
            self.rank = rank
        else:
            raise exceptions.InvalidRankCardException('invalid rank')

        if suit.lower().capitalize() in Card.suits:
            self.suit = suit.lower().capitalize()
        else:
            raise exceptions.InvalidSuitCardException('invalid suit')

    def __repr__(self) -> str:
        '''Return string representation of card.'''
        return (
            f"{self.__class__.__name__}(rank={self.rank!r}, suit={self.suit!r})"
        )

    def __hash__(self) -> int:
        '''Check object hash.'''
        # TODO: better alternative
        return hash((self.rank, self.suit))

    def __eq__(self, other: object) -> bool:
        '''Check if card is equal another card.'''
        if other.__class__ is not self.__class__:
            return NotImplemented
        return ((self.rank, self.suit) == (other.rank, other.suit
                                           )  # type: ignore
                )

    def __gt__(self, other: 'Card') -> bool:
        '''Check if card is greater than other.'''
        if not other:
            return True
        if self.suit == other.suit:
            return Card.ranks.index(self.rank) > Card.ranks.index(other.rank)
        elif self.suit == 'S':
            return True
        elif other.suit == 'S':
            return False
        else:
            raise exceptions.InvalidComparisonCardException(
                'except for invalid comparison')
Beispiel #2
0
class Deck(db.Model):
    '''Provide deck object.'''

    id = db.Column(db.Integer, primary_key=True)
    cards = db.relationship('Card',
                            secondary=cards,
                            lazy='subquery',
                            backref=db.backref('deck_of_cards', lazy=True))
    max_size = 52

    def __init__(self) -> None:
        '''Initialize Deck.'''
        for rank in Card.ranks:
            for suit in Card.suits:
                self.cards.append(Card(rank, suit))

    def __iter__(self) -> 'Deck':
        '''Return deck itself as iterator.'''
        return self

    def __next__(self) -> Card:
        '''Get next card instance.'''
        if len(self.cards) <= 0:
            raise StopIteration()
        card = choice(self.cards)
        self.cards.remove(card)
        return card
Beispiel #3
0
class Play(db.Model):
    '''Represent player action.'''

    book_id = db.Column(db.Integer, db.ForeignKey('book.id'), primary_key=True)
    card_id = db.Column(db.Integer, db.ForeignKey('card.id'), primary_key=True)
    player_id = db.Column(
        db.Integer, db.ForeignKey('player.id'), primary_key=True
    )

    db.relationship(
        'Book', uselist=False, backref='plays', lazy='dynamic'
    )
    db.relationship(
        'Card', uselist=False, backref='plays', lazy='dynamic'
    )
    db.relationship(
        'Player', uselist=False, backref='plays', lazy='dynamic'
    )
    db.UniqueConstraint('book_id', 'card_id', 'player_id')

    def __init__(self, book_id: int, player_id: int, card_id: int) -> None:
        self.book_id = book_id
        self.player_id = player_id
        self.card_id = card_id

    def __repr__(self) -> str:
        '''Return string representation of card.'''
        play = dedent(f"""\
            book_id={self.book_id!r},\
            player_id={self.player_id!r},\
            card={self.card!r}\
        """)
        return (
            f"{self.__class__.__name__}({play})"
        )

    @property
    def card(self) -> Card:
        return Card.query.get(self.card_id)
Beispiel #4
0
# -*- coding: utf-8 -*-
# copyright: (c) 2020 by Jesse Johnson.
# license: Apache 2.0, see LICENSE for more details.
'''Provide card package.'''

from secrets import choice

from spades import db
from spades.game.models.card import Card

cards = db.Table(
    'deck_of_cards',
    db.Column('card_id',
              db.Integer,
              db.ForeignKey('card.id'),
              primary_key=True),
    db.Column('deck_id',
              db.Integer,
              db.ForeignKey('deck.id'),
              primary_key=True)
    # db.Column('card_rank', db.String(1)),
    # db.Column('card_suit', db.String(1)),
    # db.ForeignKeyConstraint(
    #     ['card_rank', 'card_suit'], ['card.rank', 'card.suit']
    # )
)


class Deck(db.Model):
    '''Provide deck object.'''
Beispiel #5
0
class Player(db.Model):
    '''Provide player object.'''

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), nullable=False, unique=True)
    hand = db.relationship('Hand', uselist=False, back_populates='player')

    def __init__(self, username: str) -> None:
        '''Initialize player.'''
        self.username = username

        # TODO: values are round based
        self.__books: Set[Book] = set()
        self.__bid: Optional[int] = None
        self.__bags: int = 0
        self.__score: int = 0

    @property
    def score(self) -> int:
        '''Get player score.'''
        return self.__score

    @score.setter
    def score(self, clean: bool = False) -> None:
        '''Score players hand.'''
        # TODO overtricks
        books = len(self.books)
        if self.bid == 0:
            if books == 0:
                score = 50
            else:
                score = -50
        elif self.bid >= books:
            if self.bid > books:
                bags = self.bid - books
                score = books * 10
                if (self.__bags + bags) < 10:
                    self.__bags += bags
                    score += bags
                else:
                    score -= (100 - bags)
                    self.__bags = 0
            else:
                score = books * 10
        else:
            score = books * -10
        if clean:
            self.__books = set()
            self.__bid = None
            Hand.spades_broken = False
        self.__score = score

    # @property
    # def hand(self) -> Optional[Hand]:
    #     '''Get player hand.'''
    #     return self.

    # @hand.setter
    # def hand(self, hand: Hand) -> None:
    #     '''Set player hand.'''
    #     self.hand = hand

    @property
    def books(self) -> Set[Book]:
        '''Get awarded books.'''
        return self.__books

    @books.setter
    def books(self, book: Book) -> None:
        '''Get player books won.'''
        self.__books.add(book)

    @property
    def bid(self) -> Optional[int]:
        '''Get players bid.'''
        return self.__bid

    @bid.setter
    def bid(self, bid: int) -> None:
        '''Set players bid.'''
        self.__bid = bid

    def play_card(self, rank: str, suit: str) -> Optional[Card]:
        '''Play card from players hand.'''
        if self.hand and self.hand.cards:
            return self.hand.pull_card(rank, suit)
        else:
            raise exceptions.EmptyHandSizeException(
                'player has no cards to play')
Beispiel #6
0
class Game(db.Model):
    '''Provide game object.'''

    id = db.Column(db.Integer, primary_key=True)
Beispiel #7
0
class Hand(db.Model):
    '''Provide player hand object.'''

    # TODO: lookup stack
    spades_broken = False
    max_size = 13

    id = db.Column(db.Integer, primary_key=True)
    player_id = db.Column(db.Integer, db.ForeignKey('player.id'))
    player = db.relationship('Player', back_populates='hand')
    cards = db.relationship('Card',
                            secondary=cards,
                            lazy='subquery',
                            backref=db.backref('hand_of_cards', lazy=True))

    def __repr__(self) -> str:
        '''Return string representation of card.'''
        return f"{self.__class__.__name__}(hand={self.cards!r})"

    def __len__(self) -> int:
        '''Return number of items.'''
        return len(self.cards)

    def __iter__(self) -> 'Hand':
        '''Return hand itself as iterator.'''
        self.__count = 0
        return self

    def __next__(self) -> Card:
        '''Get next card instance.'''
        if self.__count >= len(self.cards):
            raise StopIteration()
        card: Card = self.cards[self.__count]
        self.__count += 1
        return card

    @property
    def to_json(self):
        '''Get json instance.'''
        return (json.dumps(self.cards, cls=CardEncoder))

    def list_suit(self, suit: str) -> List[str]:
        '''List items of a suit.'''
        return [c.rank for c in self.cards if c.suit == suit]

    def get_suit(self, suit: str) -> List[Card]:
        '''Get all items of a suit.'''
        return [c for c in self.cards if c.suit == suit]

    def playable(self, suit: str = None) -> List[Card]:
        '''Get all playable cards.'''
        if not suit and not Hand.spades_broken:
            hand = [c for c in self.cards if c.suit != 'S']
            return self.cards if hand == [] else hand
        elif suit and len(self.get_suit(suit)) > 0:
            return self.get_suit(suit)
        else:
            return self.cards

    def add_card(self, card: Card) -> None:
        '''Add card to player hand.'''
        if len(self.cards) < Hand.max_size:
            if card not in self.cards:
                self.cards.append(card)
            else:
                exceptions.InvalidDeckException(
                    'duplicate card already in hand')
        else:
            raise exceptions.MaxHandSizeException('maximum hand size')

    def pull_card(self, rank: str, suit: str) -> Card:
        '''Pull card from hand to play.'''
        # TODO change relationship
        card = Card.query.filter(Card.rank == rank, Card.suit == suit).first()
        print('----cards----', card)
        if card in self.cards:
            if card.suit == 'S':
                Hand.spades_broken = True
            self.cards.remove(card)
            return card
        raise exceptions.IllegalPlayException('player does not hold card')