From 488c274dcdfd3fc3dc4dd1314ab115956df88596 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Mon, 22 Dec 2025 16:45:59 +0100 Subject: [PATCH] Add tests --- coverage | 101 +++++++++++++++++++ hand.go | 39 +++++++- hand_test.go | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 coverage create mode 100644 hand_test.go diff --git a/coverage b/coverage new file mode 100644 index 0000000..306e935 --- /dev/null +++ b/coverage @@ -0,0 +1,101 @@ +mode: set +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:14.43,16.21 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:16.21,18.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:20.2,26.26 3 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:26.26,27.18 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:27.18,29.4 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:30.3,34.10 4 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:34.10,36.4 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:37.3,37.58 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:39.2,39.33 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:68.38,69.42 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:69.42,71.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:73.2,75.28 3 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:75.28,78.3 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:80.2,83.27 3 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:83.27,84.25 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:84.25,86.4 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:87.3,87.79 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:90.2,95.27 3 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:95.27,97.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:98.2,98.41 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:98.41,99.41 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:99.41,101.4 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:102.3,102.39 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:105.2,106.27 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:106.27,108.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:109.5,109.48 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:109.48,112.29 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:112.29,114.4 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:118.2,118.26 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:118.26,120.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:121.2,121.50 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:121.50,123.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:124.2,124.13 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:124.13,126.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:127.2,127.16 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:127.16,129.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:130.2,130.26 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:130.26,132.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:133.2,133.50 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:133.50,135.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:136.2,136.26 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:136.26,138.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:140.2,140.65 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:143.44,145.25 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:145.25,146.47 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:146.47,148.9 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:151.2,151.11 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:151.11,153.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:155.2,155.128 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:155.128,157.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:159.2,159.17 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:164.41,168.43 3 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:168.43,170.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:171.2,171.43 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:171.43,173.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:175.2,175.49 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:175.49,176.56 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:176.56,178.4 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:179.3,179.56 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:179.56,181.4 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:184.2,184.10 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:188.53,189.26 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:189.26,191.3 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:193.2,196.25 2 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:196.25,197.30 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:197.30,198.31 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:198.31,199.32 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:199.32,200.33 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:200.33,206.26 3 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:206.26,208.8 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:208.13,211.46 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:211.46,213.9 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\hand.go:221.2,221.22 1 1 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:12.29,14.17 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:14.17,17.3 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:18.2,21.22 3 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:21.22,25.22 3 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:25.22,26.12 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:29.3,29.37 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:29.37,32.12 3 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:35.3,38.17 3 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:38.17,40.12 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:43.3,44.77 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:49.39,51.16 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:51.16,54.3 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:55.2,64.21 5 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:64.21,67.54 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:67.54,68.12 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:71.3,74.17 3 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:74.17,75.12 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:78.3,78.69 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:81.2,82.37 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:82.37,83.38 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:83.38,94.18 7 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:95.11,96.109 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:97.11,98.109 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:99.12,100.58 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:103.4,104.11 2 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:107.2,107.46 1 0 +C:\Users\David\My Drive (roboxgame882@gmail.com)\UNI\Repos\se-poker\main.go:112.13,120.2 5 0 diff --git a/hand.go b/hand.go index 3016787..1579914 100644 --- a/hand.go +++ b/hand.go @@ -182,4 +182,41 @@ func (h *Hand) Compare(other *Hand) int { } return 0 -} \ No newline at end of file +} + +// FindBestHand finds the best 5-card hand from 7 given cards. +func FindBestHand(sevenCards []Card) (*Hand, error) { + if len(sevenCards) != 7 { + return nil, fmt.Errorf("expected 7 cards, got %d", len(sevenCards)) + } + + var bestHand *Hand + + // Generate all combinations of 5 cards from 7 + for i := 0; i < 7; i++ { + for j := i + 1; j < 7; j++ { + for k := j + 1; k < 7; k++ { + for l := k + 1; l < 7; l++ { + for m := l + 1; m < 7; m++ { + currentCards := []Card{ + sevenCards[i], sevenCards[j], sevenCards[k], sevenCards[l], sevenCards[m], + } + currentHand := &Hand{Cards: currentCards} + + if bestHand == nil { + bestHand = currentHand + } else { + // Compare currentHand with bestHand + // h.Compare(other) returns 1 if h wins, 2 if other wins, 0 for tie + if currentHand.Compare(bestHand) == 1 { + bestHand = currentHand + } + } + } + } + } + } + } + + return bestHand, nil +} diff --git a/hand_test.go b/hand_test.go new file mode 100644 index 0000000..1e58dc9 --- /dev/null +++ b/hand_test.go @@ -0,0 +1,274 @@ +package main + +import ( + "reflect" + "testing" +) + +func TestNewHand(t *testing.T) { + tests := []struct { + input string + expected *Hand + expectedErr bool + }{ + { + input: "H2 S3 C4 D5 H6", + expected: &Hand{Cards: []Card{ + {Suit: "H", Value: 2}, + {Suit: "S", Value: 3}, + {Suit: "C", Value: 4}, + {Suit: "D", Value: 5}, + {Suit: "H", Value: 6}, + }}, + expectedErr: false, + }, + { + input: "CT CJ CQ CK CA", + expected: &Hand{Cards: []Card{ + {Suit: "C", Value: 10}, + {Suit: "C", Value: 11}, + {Suit: "C", Value: 12}, + {Suit: "C", Value: 13}, + {Suit: "C", Value: 14}, + }}, + expectedErr: false, + }, + { + input: "Invalid Input", + expected: nil, + expectedErr: true, + }, + { + input: "H2 S3 C4 D5", // Not 5 cards + expected: nil, + expectedErr: true, + }, + { + input: "H2 S3 C4 D5 Hx", // Invalid card value + expected: nil, + expectedErr: true, + }, + } + + for _, tt := range tests { + hand, err := NewHand(tt.input) + if (err != nil) != tt.expectedErr { + t.Errorf("NewHand(%q) error = %v, expectedErr %v", tt.input, err, tt.expectedErr) + continue + } + if !tt.expectedErr && !reflect.DeepEqual(hand, tt.expected) { + t.Errorf("NewHand(%q) got = %v, want %v", tt.input, hand, tt.expected) + } + } +} + +func TestEvaluateHandValues(t *testing.T) { + tests := []struct { + name string + input string + expected HandCategory + }{ + {"Royal Flush", "CT CJ CQ CK CA", RoyalFlush}, + {"Straight Flush", "D8 D9 DT DJ DQ", StraightFlush}, + {"Four of a Kind", "HT SA ST DT CT", FourOfAKind}, + {"Full House", "H2 SQ C2 D2 CQ", FullHouse}, + {"Flush", "HK HQ H2 H4 H5", Flush}, + {"Straight", "H3 S7 H5 D6 C4", Straight}, + {"Three of a Kind", "H2 SQ S2 D2 CK", ThreeOfAKind}, + {"Two Pair", "H5 SQ C5 DT CT", TwoPair}, + {"Pair", "H3 S8 H5 D8 CA", Pair}, + {"High Card", "H3 S8 H5 D4 CA", HighCard}, + {"Straight Wheel", "H4 S5 HA D3 C2", Straight}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + hand, err := NewHand(tt.input) + if err != nil { + t.Fatalf("Failed to create hand for %s: %v", tt.input, err) + } + result := hand.Evaluate() + if result.Category != tt.expected { + t.Errorf("Hand: %s, Expected %s, got %s", tt.input, handNames[tt.expected], handNames[result.Category]) + } + }) + } +} + +func TestCompareHands(t *testing.T) { + tests := []struct { + name string + hand1 string + hand2 string + expected int // 1 if hand1 wins, 2 if hand2 wins, 0 for tie + }{ + {"Royal Flush vs Straight Flush", "CT CJ CQ CK CA", "D8 D9 DT DJ DQ", 1}, + {"Straight Flush vs Four of a Kind", "D8 D9 DT DJ DQ", "HT SA ST DT CT", 1}, + {"Four of a Kind vs Full House", "HT SA ST DT CT", "H2 SQ C2 D2 CQ", 1}, + {"Full House vs Flush", "H2 SQ C2 D2 CQ", "HK HQ H2 H4 H5", 1}, + {"Flush vs Straight", "HK HQ H2 H4 H5", "H3 S7 H5 D6 C4", 1}, + {"Straight vs Three of a Kind", "H3 S7 H5 D6 C4", "H2 SQ S2 D2 CK", 1}, + {"Three of a Kind vs Two Pair", "H2 SQ S2 D2 CK", "H5 SQ C5 DT CT", 1}, + {"Two Pair vs Pair", "H5 SQ C5 DT CT", "H3 S8 H5 D8 CA", 1}, + {"Pair vs High Card", "H3 S8 H5 D8 CA", "H3 S8 H5 D4 C2", 1}, + {"Tie - Same Royal Flush", "CT CJ CQ CK CA", "CT CJ CQ CK CA", 0}, + {"Tie - Same Straight Flush", "D8 D9 DT DJ DQ", "D8 D9 DT DJ DQ", 0}, + {"Tie - Higher Straight Flush", "S8 S9 ST SJ SQ", "D8 D9 DT DJ DQ", 0}, + {"Tie - Four of a Kind (higher value)", "HA SA DA CA H2", "HK SK DK CK H2", 1}, + {"Tie - Four of a Kind (same value, higher kicker)", "HA SA DA CA H3", "HA SA DA CA H2", 1}, + {"Tie - Full House (higher trips)", "HA SA DA H2 C2", "HK SK DK H2 C2", 1}, + {"Tie - Full House (same trips, higher pair)", "HA SA DA H3 C3", "HA SA DA H2 C2", 1}, + {"Tie - Flush (higher card)", "HA H9 H8 H7 H5", "HA H9 H8 H7 H4", 1}, + {"Tie - Straight (higher card)", "S9 ST SJ SQ SK", "S8 S9 ST SJ SQ", 1}, + {"Tie - Three of a Kind (higher trips)", "HA SA DA H3 C4", "HK SK DK H3 C4", 1}, + {"Tie - Three of a Kind (same trips, higher kicker)", "HA SA DA H5 C4", "HA SA DA H3 C2", 1}, + {"Tie - Two Pair (higher top pair)", "HA SA H2 C2 DK", "HK SK H2 C2 DA", 1}, + {"Tie - Two Pair (same top pair, higher second pair)", "HA SA H3 C3 DK", "HA SA H2 C2 DK", 1}, + {"Tie - Two Pair (same pairs, higher kicker)", "HA SA H2 C2 DQ", "HA SA H2 C2 DJ", 1}, + {"Tie - Pair (higher pair)", "HA SA H2 C3 D4", "HK SK H2 C3 D4", 1}, + {"Tie - Pair (same pair, higher kicker)", "HA SA H5 C3 D4", "HA SA H4 C2 D5", 1}, + {"Tie - High Card (higher card)", "HA SK CJ D9 H7", "HQ SK CJ D9 H7", 1}, + {"Tie - High Card (all equal)", "HA SK CJ D9 H7", "HA SK CJ D9 H7", 0}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + hand1, err1 := NewHand(tt.hand1) + hand2, err2 := NewHand(tt.hand2) + if err1 != nil || err2 != nil { + t.Fatalf("Failed to create hands: %v, %v", err1, err2) + } + + result := hand1.Compare(hand2) + if result != tt.expected { + t.Errorf("CompareHands(%s, %s) Expected %d, got %d", tt.hand1, tt.hand2, tt.expected, result) + } + }) + } +} + +func TestFindBestHand(t *testing.T) { + tests := []struct { + name string + sevenCards []Card + expected *Hand + expectedErr bool + }{ + { + name: "Royal Flush from 7 cards", + sevenCards: []Card{ + {Suit: "C", Value: 2}, {Suit: "C", Value: 10}, {Suit: "C", Value: 11}, {Suit: "C", Value: 12}, + {Suit: "C", Value: 13}, {Suit: "C", Value: 14}, {Suit: "H", Value: 7}, + }, + expected: &Hand{Cards: []Card{{Suit: "C", Value: 14}, {Suit: "C", Value: 13}, {Suit: "C", Value: 12}, {Suit: "C", Value: 11}, {Suit: "C", Value: 10}}}, + expectedErr: false, + }, + { + name: "Straight Flush from 7 cards", + sevenCards: []Card{ + {Suit: "D", Value: 8}, {Suit: "D", Value: 9}, {Suit: "D", Value: 10}, {Suit: "D", Value: 11}, + {Suit: "D", Value: 12}, {Suit: "S", Value: 5}, {Suit: "C", Value: 2}, + }, + expected: &Hand{Cards: []Card{{Suit: "D", Value: 12}, {Suit: "D", Value: 11}, {Suit: "D", Value: 10}, {Suit: "D", Value: 9}, {Suit: "D", Value: 8}}}, + expectedErr: false, + }, + { + name: "Four of a Kind from 7 cards", + sevenCards: []Card{ + {Suit: "H", Value: 10}, {Suit: "S", Value: 10}, {Suit: "D", Value: 10}, {Suit: "C", Value: 10}, + {Suit: "H", Value: 2}, {Suit: "S", Value: 3}, {Suit: "D", Value: 4}, + }, + expected: &Hand{Cards: []Card{{Suit: "H", Value: 10}, {Suit: "S", Value: 10}, {Suit: "D", Value: 10}, {Suit: "C", Value: 10}, {Suit: "D", Value: 4}}}, + expectedErr: false, + }, + { + name: "Full House from 7 cards", + sevenCards: []Card{ + {Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}, {Suit: "C", Value: 3}, + {Suit: "H", Value: 3}, {Suit: "S", Value: 7}, {Suit: "D", Value: 8}, + }, + expected: &Hand{Cards: []Card{{Suit: "H", Value: 3}, {Suit: "C", Value: 3}, {Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}}}, + expectedErr: false, + }, + { + name: "Flush from 7 cards", + sevenCards: []Card{ + {Suit: "H", Value: 14}, {Suit: "H", Value: 12}, {Suit: "H", Value: 10}, {Suit: "H", Value: 8}, + {Suit: "H", Value: 6}, {Suit: "S", Value: 5}, {Suit: "D", Value: 4}, + }, + expected: &Hand{Cards: []Card{{Suit: "H", Value: 14}, {Suit: "H", Value: 12}, {Suit: "H", Value: 10}, {Suit: "H", Value: 8}, {Suit: "H", Value: 6}}}, + expectedErr: false, + }, + { + name: "Straight from 7 cards", + sevenCards: []Card{ + {Suit: "H", Value: 5}, {Suit: "S", Value: 6}, {Suit: "C", Value: 7}, {Suit: "D", Value: 8}, + {Suit: "H", Value: 9}, {Suit: "S", Value: 2}, {Suit: "C", Value: 3}, + }, + expected: &Hand{Cards: []Card{{Suit: "H", Value: 9}, {Suit: "D", Value: 8}, {Suit: "C", Value: 7}, {Suit: "S", Value: 6}, {Suit: "H", Value: 5}}}, + expectedErr: false, + }, + { + name: "Three of a Kind from 7 cards", + sevenCards: []Card{ + {Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}, {Suit: "C", Value: 7}, + {Suit: "H", Value: 8}, {Suit: "S", Value: 9}, {Suit: "D", Value: 10}, + }, + expected: &Hand{Cards: []Card{{Suit: "D", Value: 10}, {Suit: "S", Value: 9}, {Suit: "H", Value: 8}, {Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}}}, + expectedErr: false, // expected cards will be sorted by value inside Evaluate() + }, + { + name: "High Card from 7 cards", + sevenCards: []Card{ + {Suit: "H", Value: 2}, {Suit: "S", Value: 4}, {Suit: "C", Value: 6}, {Suit: "D", Value: 8}, + {Suit: "H", Value: 10}, {Suit: "S", Value: 3}, {Suit: "C", Value: 5}, + }, + expected: &Hand{Cards: []Card{{Suit: "C", Value: 6}, {Suit: "C", Value: 5}, {Suit: "S", Value: 4}, {Suit: "S", Value: 3}, {Suit: "H", Value: 2}}}, + expectedErr: false, + }, + { + name: "Invalid number of cards (less than 7)", + sevenCards: []Card{ + {Suit: "H", Value: 2}, {Suit: "S", Value: 4}, {Suit: "C", Value: 6}, {Suit: "D", Value: 8}, + {Suit: "H", Value: 10}, {Suit: "S", Value: 3}, + }, + expected: nil, + expectedErr: true, + }, + { + name: "Invalid number of cards (more than 7)", + sevenCards: []Card{ + {Suit: "H", Value: 2}, {Suit: "S", Value: 4}, {Suit: "C", Value: 6}, {Suit: "D", Value: 8}, + {Suit: "H", Value: 10}, {Suit: "S", Value: 3}, {Suit: "C", Value: 5}, {Suit: "D", Value: 7}, + }, + expected: nil, + expectedErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + hand, err := FindBestHand(tt.sevenCards) + if (err != nil) != tt.expectedErr { + t.Errorf("FindBestHand() error = %v, expectedErr %v", err, tt.expectedErr) + return + } + if !tt.expectedErr { + // The order of cards in the expected hand might not exactly match due to sorting, + // so we compare the evaluated categories and tie-breakers. + if hand == nil { + t.Fatalf("FindBestHand() returned nil hand for valid input") + } + expectedHandResult := (&Hand{Cards: tt.expected.Cards}).Evaluate() + actualHandResult := hand.Evaluate() + + if expectedHandResult.Category != actualHandResult.Category { + t.Errorf("FindBestHand() for %s: expected category %s, got %s", tt.name, handNames[expectedHandResult.Category], handNames[actualHandResult.Category]) + } + if !reflect.DeepEqual(expectedHandResult.TieBreakers, actualHandResult.TieBreakers) { + t.Errorf("FindBestHand() for %s: expected tie-breakers %v, got %v", tt.name, expectedHandResult.TieBreakers, actualHandResult.TieBreakers) + } + } + }) + } +}