Repository: zooba/deck

Issue:
Ace to Five straight/straight flush are not handled in get_poker_hand
Low-ace straight/straight flush aren't found as the sort assumes aces-high.
PR on way to add tests & support.

Comments:

Patch:
diff --git a/deck.py b/deck.py
index dc7b3a5..ab7193c 100644
--- a/deck.py
+++ b/deck.py
@@ -9,7 +9,6 @@ import itertools
 import random
 import sys
 
-
 __all__ = [
     "Card",
     "Deck",
@@ -22,7 +21,6 @@ __all__ = [
     "Value",
 ]
 
-
 _SUIT_SORT_ORDER = {
     # Handle suit-less comparisons gracefully (as highest)
     "": 10,
@@ -260,6 +258,7 @@ def get_poker_hand(cards):
     The best hand sorts last (is greater than other hands).
     """
     cards = sorted(cards, key=aces_high, reverse=True)
+    cards_low_ace = sorted(cards, key=lambda card: card.value, reverse=True)
 
     # Any jokers will have sorted to the front
     if cards and cards[0].joker:
@@ -280,9 +279,14 @@ def get_poker_hand(cards):
     is_straight = len(cards) == 5 and all(
         i[0].value == i[1] for i in zip(cards, range(cards[0].value, -5, -1))
     )
+    is_ace_low_straight = len(cards) == 5 and all(
+        i[0].value == i[1] for i in zip(cards_low_ace, range(cards_low_ace[0].value, -5, -1))
+    )
 
     if len(suits) == 1 and is_straight:
         return PokerHand.StraightFlush, aces_high(high_card)
+    if len(suits) == 1 and is_ace_low_straight:
+        return PokerHand.StraightFlush, cards_low_ace[0].value
     if of_a_kind == 4:
         return PokerHand.FourOfAKind, aces_high(of_a_kind_card)
     if of_a_kind == 3 and second_pair == 2:
@@ -291,6 +295,8 @@ def get_poker_hand(cards):
         return PokerHand.Flush, aces_high(high_card)
     if is_straight:
         return PokerHand.Straight, aces_high(high_card)
+    if is_ace_low_straight:
+        return PokerHand.Straight, cards_low_ace[0].value
     if of_a_kind == 3:
         return (PokerHand.ThreeOfAKind, aces_high(of_a_kind_card)) + (
             (aces_high(second_pair_card),) if second_pair_card else ()
@@ -520,7 +526,6 @@ class Hand(list):
         self[:] = self.sorted(order=order, reverse=reverse)
 
     def __format__(self, spec):
-        import re
 
         if not spec:
             spec = "4.3"
diff --git a/readme.md b/readme.md
index fe76ca6..f059b60 100644
--- a/readme.md
+++ b/readme.md
@@ -210,7 +210,7 @@ The result of the function is a tuple containing first a `PokerHand` value, foll
 Suits are not taken into account for breaking ties.
 
 ```python
->>> from deck import Deck, get_poker_hand
+>>> from deck import Deck, get_poker_hand, Hand, HandSort
 >>> deck = Deck(include_jokers=False)
 >>> deck.shuffle()
 >>> p1, p2 = deck.deal_hands(hands=2, cards=5)


Test patch:
diff --git a/deck-tests.py b/deck-tests.py
index 1e43659..dc33044 100644
--- a/deck-tests.py
+++ b/deck-tests.py
@@ -135,6 +135,17 @@ class PokerHandTests(unittest.TestCase):
         hand = deck.get_poker_hand(cards)
         assert hand == (deck.PokerHand.Straight, 6)
 
+    def test_straight_with_low_ace(self):
+        cards = [
+            Card("Spades", 1),
+            Card("Spades", 2),
+            Card("Clubs", 3),
+            Card("Hearts", 4),
+            Card("Diamonds", 5),
+        ]
+        hand = deck.get_poker_hand(cards)
+        assert hand == (deck.PokerHand.Straight, 5)
+
     def test_flush(self):
         cards = [
             Card("Clubs", 2),
@@ -179,6 +190,17 @@ class PokerHandTests(unittest.TestCase):
         hand = deck.get_poker_hand(cards)
         assert hand == (deck.PokerHand.StraightFlush, 9)
 
+    def test_straight_flush_with_low_ace(self):
+        cards = [
+            Card("Clubs", 1),
+            Card("Clubs", 2),
+            Card("Clubs", 3),
+            Card("Clubs", 4),
+            Card("Clubs", 5),
+        ]
+        hand = deck.get_poker_hand(cards)
+        assert hand == (deck.PokerHand.StraightFlush, 5)
+
     def test_compare_1(self):
         cards = [
             Card("Spades", 2),