poker-toolkit 0.0.6
A dead-simple Poker Toolkit written in Python.
Requires Python: >=3.6

# Poker Toolkit

A dead-simple Poker Toolkit written in Python. Its purpose is to help evaluating hands and
providing other useful information about the game.

### How to use

```python

from poker_toolkit.hand import Hand
from poker_toolkit.evaluation import has_three_of_a_kind

hand = Hand(["Js", "Jh", "Jc", "9h", "7s"])
result = has_three_of_a_kind(hand)
```

### API

##### Evaluation
* `evaluation.has_one_pair(hand: Hand) -> bool`
* `evaluation.has_two_pairs(hand: Hand) -> bool`
* `evaluation.has_three_of_a_kind(hand: Hand) -> bool`
* `evaluation.has_straight(hand: Hand) -> bool`
* `evaluation.has_flush(hand: Hand) -> bool`
* `evaluation.has_full_house(hand: Hand) -> bool`
* `evaluation.has_four_of_a_kind(hand: Hand) -> bool`
* `evaluation.has_straight_flush(hand: Hand) -> bool`
* `evaluation.has_royal_flush(hand: Hand) -> bool`
* `evaluation.evaluate(hand: Hand) -> List`
    * Evaluate a Hand and return a list of all the figures possible.
* `evaluation.compare(hand1: Hand, hand2: Hand) -> int`
    * Compare two hands and return:
        * 1: If the first hand is stronger
        * 2: If the second hand is stronger
        * 3: If both hands have the same strength
* `evaluation.select_best_hand(hands: List[Hand]) -> (Hand, int)`
    * Select the best Hand (and its figures) from a list of Hands.

##### Generation

* `generation.generate_random_hands(num_cards_per_hand: int, num_hands: int, figure_code: int) -> List[Hand]`
    * It will randomly generate a certain number of Hands. If [figure_code] is provided, it will only generate Hands where that figure is the highest for that Hand.
* `generation.generate_hand_from_random_cards(incomplete_list_of_cards: List, desired_hand_size: int) -> Hand`
    * It will take an incomplete Hand (list of cards) and a desired hand size, and it will create a Hand for you.
* `generation.generate_hands_images(hands: Hand, folder_to_save_img: str) -> Optional[str]`
    * It will generate and store JPG images for each one of the Hands provided by parameters.
* `generation.generate_hands_permutations(hands: Hand) -> Optional[str]`
    * It will generate all possible permutations to each one of the Hands provided by parameters.
* `generation.generate_dataset_of_images(max_number_images_per_figure: int, folder_to_save_img: str, valid_pct: int)`
    * It will generate a dataset of images (organized per figure) by performing permutations to a sample of hands. It will distribute automatically the images in "train" and "valid" folders.

##### Calculation

* `calculation.calculate_pot_odds(pot_size: float, call_size: float) -> float`
    * Calculate the Pot Odds based on the pot and call size.
* `calculation.calculate_outs(hand: Hand) -> int`
    * Calculate number of outs based on a Drawing Hand (Hands close to have a figure)
* `calculation.calculate_intrinsic_hand_equity(hand: Hand) -> (int, int)`
    * Calculate the approximate intrinsic equity value based on the Hand outs and current turn (determined based on the number of cards in the Hand). It follows the Rule of 2 and 4.
* `calculation.calculate_hand_equity_versus_a_list_of_hands_from_range(hand: Hand, list_of_hands: List[Hand]) -> (float, float, float)`
    * Calculate Hand equity versus a list of hands from range by comparing Hands one-by-one and calculating the percentage of wins, loses and ties. It returns: (pct_wins, pct_loses, pct_ties)
* `calculation.calculate_list_of_possible_hands_from_range_matrix_and_flopped_cards(range_matrix: List[str], flopped_cards: List[str], dead_cards: List[str]) -> List[Hand]`
    * Calculate a list of possible hands based on the range matrix values and flopped cards. It will also exclude cards provided on the "dead_cards" list.

##### Assistance

* `assistance.decision_assistance_based_on_equity_and_pot_odds(hand: Hand, pot_size: float, call_size: float) -> Dict`
    * Provide stats to assist in the process of deciding whether betting/calling further is the best option (has EV+ or EV-)

##### Utils

* `utils.build_deck() -> List`
    * Useful method to generate a deck of cards by combining all valid Suits and Values.
* `utils.get_figure_name_from_code(code: int) -> str`
    * Based on the figure code (e.g., 10, 9, 8...), it will return a figure name.
* `utils.get_all_combinations_from_starting_hand(starting_hand: str, excluded_cards: List = None) -> List[List]`
    * Get all suit combinations based on a starting hand and a rule ("o" -- off-suited or "s" -- suited). For example:
        * `starting_hand`: `AKo`
        * `combinations`: `[['As', 'Kh'], ['Kh', 'Ad'], ['Kd', 'Ac'], ...]`

### Figures Codes
* `10`: `royal flush`
* `9`: `straight flush`
* `8`: `four of a kind`
* `7`: `full house`
* `6`: `flush`
* `5`: `straight`
* `4`: `three of a kind`
* `3`: `two pair`
* `2`: `one pair`
* `1`: `high card`

### TODO

* Add resolution mechanism in the event of ties.
* Add validator to verify that 2 exact equal hands (inc. same order) are not generated and added to the same list.


### Tests

```bash
pytest
```

### License

MIT