from __future__ import annotations from random import shuffle from typing import Literal import inquirer class Card: """ Standard poker card. Attributes: value: Absolute card value, between 2 and 14 (for the ace). symbol (int): Symbol of the card, as an integer. 0 is hearts; 1 is diamonds, 2 is clubs and 3 is spades. """ SYMBOLS: dict[int, str] = {0: "Hearts", 1: "Diamonds", 2: "Clubs", 3: "Spades"} VALUES: dict[int, str] = {11: "Jack", 12: "Queen", 13: "King", 14: "Ace"} value: int = 2 symbol: Literal[0, 1, 2, 3] = 0 def __init__(self, value: int, symbol: Literal[0, 1, 2, 3]): self.symbol = symbol self.value = value def __lt__(self, other: Card): if isinstance(other, Card): return self.value < other.value raise TypeError(f"Can't compare {type(other)}") def __eq__(self, other: Card): if isinstance(other, Card): return self.value < other.value raise TypeError(f"Can't compare {type(other)}") def __str__(self): return f"{self.name} de {self.symbol_name}" @property def name(self): """Get the name of this card.""" return self.VALUES.get(self.value, str(self.value)) @property def symbol_name(self): """Get the name of the symbol of this card.""" return self.SYMBOLS.get(self.symbol, "N/A") @property def full_name(self) -> str: """Get the full name of this card, value and symbol.""" return f"{self.name} of {self.symbol_name}" class Deck: """A deck of cards.""" _cards: list[Card] = None def __init__(self, full: bool = False, shuffled: bool = False): """ Initialize a deck with cards. Args: full: If True, fill with all possible cards. shuffled: If True, shuffle the content of the deck directly. """ self._cards = [] if full is True: for value in range(2, 15): for symbol in range(0, 4): self._cards.append(Card(value, symbol)) # noqa if shuffled is True: self.shuffle() def __bool__(self) -> bool: """ Tell if the deck is empty or not. Returns: True: if not empty False: otherwise. """ return bool(self._cards) def shuffle(self): """Shuffle the deck so the cards are not ordered by value.""" shuffle(self._cards) def pop_to(self, other: Deck) -> None: """Remove last card from deck and add to another deck.""" other._cards.append(self._cards.pop()) def pop(self, index: int) -> Card: """Get card at index in deck and remove from the deck.""" return self._cards.pop(index) def display_cards(self) -> None: """Show available cards with their respective index in the deck.""" for index, card in enumerate(self._cards): print(f"{index:02}: {card.full_name}", end=" / ") print() def pick_input(self) -> int: """ Ask the user to pick a card from the deck. Returns: The selected index for a card. """ q = [inquirer.List("selection", message="Pick a card", choices=self.card_selection, default=0)] return inquirer.prompt(q)["selection"] @property def card_selection(self) -> list[tuple[str, int]]: """ Get available cards with their respective index in the deck. Returns: A list of tuples, where each tuple contains two elements: - The first element being the card name - The second element being the card index """ return [(c.full_name, index) for index, c in enumerate(self._cards)]