Class: HandRepository

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/rora/repository/hand_repository.rb

Constant Summary collapse

HEART_FLUSH =
32
DIAMOND_FLUSH =
243
SPADE_FLUSH =
3125
CLUB_FLUSH =
16807

Instance Method Summary collapse

Constructor Details

#initializeHandRepository

Returns a new instance of HandRepository.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/rora/repository/hand_repository.rb', line 12

def initialize
  @hands = Array.new
  
  @five_card_table = Hash.new
  CSV.foreach("lib/rora/5-card-hands.csv") do |row|
    @five_card_table[row[1].to_i] = [row[0].to_i, row[3], row[4]]
  end

  @seven_card_table = Hash.new
  CSV.foreach("lib/rora/7-card-hands.csv") do |row|
    @seven_card_table[row[1].to_i] = [row[0].to_i, row[4], row[5]]
  end

  @flushes_table = Hash.new
  CSV.foreach("lib/rora/flushes.csv") do |row|
    @flushes_table[row[0].to_i] = [row[1].to_i, row[2]]
  end
end

Instance Method Details

#evaluate_5_card_hand(cards) ⇒ Object



31
32
33
34
# File 'lib/rora/repository/hand_repository.rb', line 31

def evaluate_5_card_hand(cards)
  flush = Hand.new(cards).flush?
  @five_card_table.fetch(cards.inject(1) {|product, card| product * card.rank.id} * (flush ? 67 : 1))
end

#evaluate_7_card_hand(cards) ⇒ Object



36
37
38
39
40
# File 'lib/rora/repository/hand_repository.rb', line 36

def evaluate_7_card_hand(cards)
  key = generate_suit_key(cards)
  flush = has_flush?(key)
  flush ? get_best_hand(cards, key) : @seven_card_table.fetch(cards[0].rank.id * cards[1].rank.id * cards[2].rank.id * cards[3].rank.id * cards[4].rank.id * cards[5].rank.id * cards[6].rank.id)
end

#has_flush?(key) ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/rora/repository/hand_repository.rb', line 42

def has_flush?(key)
  key % HEART_FLUSH == 0 || key % DIAMOND_FLUSH == 0 || key % SPADE_FLUSH == 0 || key % CLUB_FLUSH == 0
end

#list(arguments = nil) ⇒ Object

Returns all possible poker hands.

No Arguments If no arguments are provided, this method will return all 2,598,960 (52c5) poker hands.

Starting Hand If a starting hand is provided as an argument, this method returns all poker hands that can be made with the given starting hand. A standard deck of 52 cards is assumed. Exactly 19,600 (50c3) 5-card poker hands will be returned for any given starting hand.

Starting Hand and Deck If a deck is provided along with a starting hand, this method will return all poker hands that can be made with the given starting hand and cards that remain in the deck.

Starting Hand and Board If a board is provided along with a starting hand, this method will return all poker hands that can be made with the given starting hand and board. In this scenario, a standard deck of 52 cards is assumed. A deck will contain exactly 50 cards after the starting hand has been dealt. The deck will contain 47 cards after the flop, 46 cards after the turn and 45 cards after the river.

Once the community cards have been dealt, there are 21 (7c5) ways to choose a 5-card poker hand from the 5 community cards and 2 hole cards. The total number of hands that will be returned from this method are as follows:

If the board has 5 community cards, flop turn & river have been dealt: 21 hands -> 21 (7c5) # 1 (45c0)

If the board has 4 community cards, flop and turn have been dealt: 966 hands -> 21 (7c5) # 46 (46c1)

If the board has 3 community cards, flop has been dealt: 22701 hands -> 21 (7c5) # 1081 (47c2)

Starting Hand, Board and Deck This method will return all poker hands that can be made with the given starting hand and cards that remain in the deck.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rora/repository/hand_repository.rb', line 88

def list(arguments=nil)
  return all_hands if arguments.nil? || arguments[:starting_hand].nil?

  starting_hand = arguments[:starting_hand]
  deck = arguments[:deck].nil? ? Deck.new : arguments[:deck]
  board = arguments[:board]
  spec_hands = Array.new

  if !board.nil?
    raise RuntimeError if board.contains_any? starting_hand.cards
    if board.cards.size == 5
      (board.cards + starting_hand.cards).combination(5).to_a.each { |cards| spec_hands << Hand.new(cards) }
    else
      deck.remove(starting_hand).remove(board).combination(5 - board.cards.size).to_a.each do |cards|
        (starting_hand.cards + board.cards + cards).combination(5).to_a.each { |cds| spec_hands << Hand.new(cds) }
      end
    end
    return spec_hands
  end

  deck.remove(starting_hand).combination(3).each { |cards| spec_hands << Hand.new(cards + starting_hand.cards) }
  spec_hands
end

#list_and_group_by_hand_score(arguments = nil) ⇒ Object

Returns unique poker hands.

While there are over 2.5 million distinct poker hands, many of these hands have the same value in poker. To elaborate on this a bit, consider the number of hands a player could have containing a pair of fours with a 10-7-6 kicker:

4♣ 4♦ 6♠ 7♥ 10♥ 4♠ 4♦ 6♠ 7♥ 10♥ 4♥ 4♦ 6♠ 7♥ 10♥ 4♣ 4♠ 6♠ 7♥ 10♥ 4♣ 4♦ 6♠ 7♥ 10♦ 4♣ 4♦ 6♠ 7♦ 10♥ 4♣ 4♦ 6♣ 7♥ 10♥ 4♣ 4♦ 6♠ 7♠ 10♥ 4♣ 4♦ 6♠ 7♦ 10♠ 4♣ 4♦ 6♣ 7♥ 10♣

This list goes on much further - in fact, there are exactly 768 distinct hand combinations that contain of exactly one pair of fours with a 10-7-6 kicker. Each of these 768 hands has the same hand value, or score.

This exercise demonstrates that the number of unique hands (that is, hands that share an identical hand score) is significantly lower than the number of distinct hands. This is because card suits don’t tend to affect the score of a hand (the only exception being a flush).

This method carries the same semantics as the list method, but returns unique hands instead of every possible hand.



139
140
141
142
143
144
145
146
147
148
# File 'lib/rora/repository/hand_repository.rb', line 139

def list_and_group_by_hand_score(arguments=nil)
  spec_hands = list(arguments)
  return spec_hands if spec_hands.nil? || spec_hands.size == 0

  hash = Hash.new
  spec_hands.each do |hand|
    hash[(hand.cards.inject(1) {|product, card| product * card.rank.id } * (hand.flush? ? 67 : 1))] = hand
  end
  hash.values
end