rora 0.0.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +59 -15
- data/Rakefile +0 -1
- data/lib/rora.rb +4 -0
- data/lib/rora/{hands.csv → 5-card-hands.csv} +0 -0
- data/lib/rora/7-card-hands.csv +323765 -0
- data/lib/rora/cards.csv +52 -0
- data/lib/rora/flushes.csv +40 -0
- data/lib/rora/model/board.rb +2 -2
- data/lib/rora/model/card.rb +17 -14
- data/lib/rora/model/deck.rb +23 -0
- data/lib/rora/model/equity.rb +18 -0
- data/lib/rora/model/hand.rb +12 -27
- data/lib/rora/model/hand_type.rb +1 -1
- data/lib/rora/model/pot.rb +1 -1
- data/lib/rora/model/rank.rb +34 -16
- data/lib/rora/model/starting_hand.rb +22 -18
- data/lib/rora/model/suit.rb +26 -11
- data/lib/rora/model/table.rb +0 -3
- data/lib/rora/repository/card_repository.rb +17 -0
- data/lib/rora/repository/hand_repository.rb +60 -20
- data/lib/rora/repository/starting_hand_repository.rb +2 -1
- data/lib/rora/utils/equity_calculator.rb +47 -0
- data/lib/rora/utils/hand_ranking_generator.rb +135 -0
- data/test/rora/model/board_test.rb +19 -20
- data/test/rora/model/card_test.rb +45 -15
- data/test/rora/model/deck_test.rb +24 -0
- data/test/rora/model/hand_test.rb +5 -29
- data/test/rora/model/hand_type_test.rb +3 -3
- data/test/rora/model/pot_test.rb +2 -2
- data/test/rora/model/rank_test.rb +10 -2
- data/test/rora/model/seat_test.rb +1 -1
- data/test/rora/model/starting_hand_test.rb +8 -16
- data/test/rora/model/suit_test.rb +3 -3
- data/test/rora/model/table_test.rb +8 -8
- data/test/rora/repository/hand_repository_test.rb +14 -16
- data/test/rora/utils/equity_calculator_test.rb +53 -0
- data/test/rora_test.rb +1 -1
- metadata +13 -6
- data/test/rora/model/game_test.rb +0 -23
data/lib/rora/model/suit.rb
CHANGED
@@ -5,12 +5,15 @@
|
|
5
5
|
# of cards has four suits: hearts, clubs, spades, and diamonds.
|
6
6
|
#
|
7
7
|
class Suit
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
attr_reader :id, :key, :value, :order
|
11
|
+
|
12
|
+
def initialize(id, key, value, order)
|
11
13
|
@id = id
|
12
14
|
@key = key
|
13
15
|
@value = value
|
16
|
+
@order = order
|
14
17
|
end
|
15
18
|
|
16
19
|
def self.values
|
@@ -21,23 +24,35 @@ class Suit
|
|
21
24
|
self.values.each do |suit|
|
22
25
|
return suit if suit.key.casecmp(key) == 0
|
23
26
|
end
|
24
|
-
raise ArgumentError, "No suit exists for key "
|
27
|
+
raise ArgumentError, "No suit exists for key '#{key}'"
|
25
28
|
end
|
26
29
|
|
27
|
-
def
|
28
|
-
|
30
|
+
def <=>(suit)
|
31
|
+
self.order <=> suit.order
|
32
|
+
end
|
33
|
+
|
34
|
+
def eql? suit
|
35
|
+
self == suit
|
29
36
|
end
|
30
37
|
|
31
38
|
def == suit
|
32
|
-
self.
|
39
|
+
self.key == suit.key
|
40
|
+
end
|
41
|
+
|
42
|
+
def hash
|
43
|
+
return self.key.ord
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
"#{@value}s"
|
33
48
|
end
|
34
49
|
|
35
50
|
class << self
|
36
51
|
private :new
|
37
52
|
end
|
38
53
|
|
39
|
-
HEART = new(
|
40
|
-
|
41
|
-
|
42
|
-
|
54
|
+
HEART = new(2, "H", "Heart", 1)
|
55
|
+
DIAMOND = new(3, "D", "Diamond", 2)
|
56
|
+
SPADE = new(5, "S", "Spade", 3)
|
57
|
+
CLUB = new(7, "C", "Club", 4)
|
43
58
|
end
|
data/lib/rora/model/table.rb
CHANGED
@@ -36,17 +36,14 @@ class Table
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def the_small_blind
|
39
|
-
raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
|
40
39
|
players.size == 2 ? the_button : the_seat_after(the_button)
|
41
40
|
end
|
42
41
|
|
43
42
|
def the_big_blind
|
44
|
-
raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
|
45
43
|
the_seat_after the_small_blind
|
46
44
|
end
|
47
45
|
|
48
46
|
def under_the_gun
|
49
|
-
raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
|
50
47
|
the_seat_after(the_big_blind)
|
51
48
|
end
|
52
49
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
class CardRepository
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@card_table = Hash.new
|
9
|
+
CSV.foreach("lib/rora/cards.csv") do |row|
|
10
|
+
@card_table[row[0]] = row[1].to_i
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(key)
|
15
|
+
@card_table.fetch(key)
|
16
|
+
end
|
17
|
+
end
|
@@ -4,16 +4,43 @@ require 'singleton'
|
|
4
4
|
class HandRepository
|
5
5
|
include Singleton
|
6
6
|
|
7
|
+
HEART_FLUSH=32
|
8
|
+
DIAMOND_FLUSH=243
|
9
|
+
SPADE_FLUSH=3125
|
10
|
+
CLUB_FLUSH=16807
|
11
|
+
|
7
12
|
def initialize
|
8
13
|
@hands = Array.new
|
9
|
-
|
10
|
-
|
11
|
-
|
14
|
+
|
15
|
+
@five_card_table = Hash.new
|
16
|
+
CSV.foreach("lib/rora/5-card-hands.csv") do |row|
|
17
|
+
@five_card_table[row[1].to_i] = [row[0].to_i, row[3], row[4]]
|
18
|
+
end
|
19
|
+
|
20
|
+
@seven_card_table = Hash.new
|
21
|
+
CSV.foreach("lib/rora/7-card-hands.csv") do |row|
|
22
|
+
@seven_card_table[row[1].to_i] = [row[0].to_i, row[4], row[5]]
|
23
|
+
end
|
24
|
+
|
25
|
+
@flushes_table = Hash.new
|
26
|
+
CSV.foreach("lib/rora/flushes.csv") do |row|
|
27
|
+
@flushes_table[row[0].to_i] = [row[1].to_i, row[2]]
|
12
28
|
end
|
13
29
|
end
|
14
30
|
|
15
|
-
def
|
16
|
-
|
31
|
+
def evaluate_5_card_hand(cards)
|
32
|
+
flush = Hand.new(cards).flush?
|
33
|
+
@five_card_table.fetch(cards.inject(1) {|product, card| product * card.rank.id} * (flush ? 67 : 1))
|
34
|
+
end
|
35
|
+
|
36
|
+
def evaluate_7_card_hand(cards)
|
37
|
+
key = generate_suit_key(cards)
|
38
|
+
flush = has_flush?(key)
|
39
|
+
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)
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_flush?(key)
|
43
|
+
key % HEART_FLUSH == 0 || key % DIAMOND_FLUSH == 0 || key % SPADE_FLUSH == 0 || key % CLUB_FLUSH == 0
|
17
44
|
end
|
18
45
|
|
19
46
|
# Returns all possible poker hands.
|
@@ -58,29 +85,28 @@ class HandRepository
|
|
58
85
|
# Starting Hand, Board and Deck
|
59
86
|
# This method will return all poker hands that can be made with the given starting
|
60
87
|
# hand and cards that remain in the deck.
|
61
|
-
def list
|
62
|
-
return
|
88
|
+
def list(arguments=nil)
|
89
|
+
return all_hands if arguments.nil? || arguments[:starting_hand].nil?
|
63
90
|
|
64
91
|
starting_hand = arguments[:starting_hand]
|
65
92
|
deck = arguments[:deck].nil? ? Deck.new : arguments[:deck]
|
66
93
|
board = arguments[:board]
|
67
|
-
|
94
|
+
spec_hands = Array.new
|
68
95
|
|
69
96
|
if !board.nil?
|
70
97
|
raise RuntimeError if board.contains_any? starting_hand.cards
|
71
98
|
if board.cards.size == 5
|
72
|
-
(board.cards + starting_hand.cards).combination(5).to_a.each { |cards|
|
73
|
-
return hands
|
99
|
+
(board.cards + starting_hand.cards).combination(5).to_a.each { |cards| spec_hands << Hand.new(cards) }
|
74
100
|
else
|
75
101
|
deck.remove(starting_hand).remove(board).combination(5 - board.cards.size).to_a.each do |cards|
|
76
|
-
(starting_hand.cards + board.cards + cards).combination(5).to_a.each { |cds|
|
102
|
+
(starting_hand.cards + board.cards + cards).combination(5).to_a.each { |cds| spec_hands << Hand.new(cds) }
|
77
103
|
end
|
78
|
-
return hands
|
79
104
|
end
|
105
|
+
return spec_hands
|
80
106
|
end
|
81
107
|
|
82
|
-
deck.remove(starting_hand).combination(3).each { |cards|
|
83
|
-
|
108
|
+
deck.remove(starting_hand).combination(3).each { |cards| spec_hands << Hand.new(cards + starting_hand.cards) }
|
109
|
+
spec_hands
|
84
110
|
end
|
85
111
|
|
86
112
|
# Returns unique poker hands.
|
@@ -110,20 +136,34 @@ class HandRepository
|
|
110
136
|
#
|
111
137
|
# This method carries the same semantics as the list method, but returns unique hands instead of
|
112
138
|
# every possible hand.
|
113
|
-
def
|
114
|
-
|
115
|
-
return
|
139
|
+
def list_and_group_by_hand_score(arguments=nil)
|
140
|
+
spec_hands = list(arguments)
|
141
|
+
return spec_hands if spec_hands.nil? || spec_hands.size == 0
|
116
142
|
|
117
143
|
hash = Hash.new
|
118
|
-
|
119
|
-
hash[
|
144
|
+
spec_hands.each do |hand|
|
145
|
+
hash[(hand.cards.inject(1) {|product, card| product * card.rank.id } * (hand.flush? ? 67 : 1))] = hand
|
120
146
|
end
|
121
147
|
hash.values
|
122
148
|
end
|
123
149
|
|
124
150
|
private
|
125
151
|
|
126
|
-
def
|
152
|
+
def get_best_hand(cards, key)
|
153
|
+
flush = @flushes_table.fetch(key)
|
154
|
+
if(flush[0] != 5)
|
155
|
+
return @seven_card_table.fetch(cards[0].uid * cards[1].uid * cards[2].uid * cards[3].uid * cards[4].uid * cards[5].uid * cards[6].uid)
|
156
|
+
end
|
157
|
+
@five_card_table.fetch(cards.inject(1) {|product, card| product * ((card.suit.key == flush[1]) ? card.rank.id : 1)} * 67)
|
158
|
+
end
|
159
|
+
|
160
|
+
def generate_suit_key(cards)
|
161
|
+
key = 1
|
162
|
+
cards.each {|card| key = key * card.suit.id}
|
163
|
+
key
|
164
|
+
end
|
165
|
+
|
166
|
+
def all_hands
|
127
167
|
if @hands.empty?
|
128
168
|
Deck.new.combination(5).each {|cards| @hands << Hand.new(cards)}
|
129
169
|
end
|
@@ -8,7 +8,8 @@ class StartingHandRepository
|
|
8
8
|
Deck.new.cards.combination(2) do |combination|
|
9
9
|
starting_hand = StartingHand.new(combination)
|
10
10
|
@all << starting_hand
|
11
|
-
|
11
|
+
hash_key = starting_hand.cards.inject(1) {|product, card| product * card.rank.id } * (starting_hand.suited? ? 67 : 1)
|
12
|
+
@distinct[hash_key] = starting_hand
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class EquityCalculator
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@hand_repository = HandRepository.instance
|
7
|
+
@best_scores = Hash.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def calculate_equity(starting_hands, board = Board.new)
|
11
|
+
raise ArgumentError, "Must have at least two starting hands for equity comparison" if (starting_hands.nil? || starting_hands.size < 2)
|
12
|
+
raise ArgumentError, "There are duplicate cards" if duplicates?(starting_hands, board)
|
13
|
+
|
14
|
+
equity_map = Hash[starting_hands.map{|starting_hand| [starting_hand, 0]}]
|
15
|
+
game = Deck.new.remove(merge(starting_hands, board)).combination(5 - board.cards.size)
|
16
|
+
|
17
|
+
game.each do |cards|
|
18
|
+
showdown(equity_map, starting_hands, board.cards + cards)
|
19
|
+
end
|
20
|
+
|
21
|
+
total_winning_hands = equity_map.inject(0) {|total, result| total += result[1]}
|
22
|
+
equity_map.inject(Hash.new) { |hash, result| hash[result[0]] = Equity.new(game.size, total_winning_hands, result); hash}
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def showdown(results, starting_hands, board_cards)
|
28
|
+
@best_scores.clear
|
29
|
+
|
30
|
+
starting_hands.each do |starting_hand|
|
31
|
+
@best_scores[starting_hand] = @hand_repository.evaluate_7_card_hand((board_cards + starting_hand.cards))[0]
|
32
|
+
end
|
33
|
+
|
34
|
+
winner = @best_scores.min_by{|key,value| value}
|
35
|
+
results[winner[0]] += 1 if(@best_scores.select {|k,v| v == winner[1]}.size == 1)
|
36
|
+
end
|
37
|
+
|
38
|
+
def duplicates?(starting_hands, board)
|
39
|
+
cards = merge(starting_hands, board)
|
40
|
+
cards.uniq.length != cards.length
|
41
|
+
end
|
42
|
+
|
43
|
+
def merge(starting_hands, board)
|
44
|
+
starting_hands.inject(board.cards) {|cards, starting_hand| cards.concat(starting_hand.cards)}
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class HandRankingGenerator
|
4
|
+
|
5
|
+
HEART_FLUSH=32
|
6
|
+
DIAMOND_FLUSH=243
|
7
|
+
SPADE_FLUSH=3125
|
8
|
+
CLUB_FLUSH=16807
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@total = 133784560
|
12
|
+
@count = 0
|
13
|
+
@scores = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_flush_map
|
17
|
+
file = File.new("flushes.csv", "w")
|
18
|
+
|
19
|
+
Suit.values().each do |suit_1|
|
20
|
+
Suit.values().each do |suit_2|
|
21
|
+
Suit.values().each do |suit_3|
|
22
|
+
Suit.values().each do |suit_4|
|
23
|
+
Suit.values().each do |suit_5|
|
24
|
+
Suit.values().each do |suit_6|
|
25
|
+
Suit.values().each do |suit_7|
|
26
|
+
key = suit_1.id * suit_2.id * suit_3.id * suit_4.id * suit_5.id * suit_6.id * suit_7.id
|
27
|
+
if(!@scores.has_key?(key))
|
28
|
+
@scores[key] = key
|
29
|
+
suit = flush_suit(key)
|
30
|
+
if(!suit.nil?)
|
31
|
+
count = flush_count([suit_1, suit_2, suit_3, suit_4, suit_5, suit_6, suit_7], suit)
|
32
|
+
file.write("#{key},#{count},#{suit}\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
file.close
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_non_flush_hand_rankings
|
47
|
+
file = File.new("7_card_non_flush_hands.csv", "w")
|
48
|
+
cds = Deck.new.cards
|
49
|
+
|
50
|
+
(0..45).each do |index_1|
|
51
|
+
((index_1 + 1)..46).each do |index_2|
|
52
|
+
((index_2 + 1)..47).each do |index_3|
|
53
|
+
((index_3 + 1)..48).each do |index_4|
|
54
|
+
((index_4 + 1)..49).each do |index_5|
|
55
|
+
((index_5 + 1)..50).each do |index_6|
|
56
|
+
((index_6 + 1)..51).each do |index_7|
|
57
|
+
cards = [cds[index_1], cds[index_2], cds[index_3], cds[index_4], cds[index_5], cds[index_6], cds[index_7]].sort
|
58
|
+
hand = get_best_hand(cards)
|
59
|
+
key = get_key(cards, hand)
|
60
|
+
if(!@scores.has_key?(key) && !hand.flush?)
|
61
|
+
@scores[key] = hand.score
|
62
|
+
file.write("#{hand.score},#{key}\n")
|
63
|
+
end
|
64
|
+
@count = @count + 1
|
65
|
+
if(@count % 1000 == 0)
|
66
|
+
puts "#{DateTime.now.strftime('%Y-%m-%d %H:%M:%S')} :: #{@count} records processed #{sprintf("%05.3f", (Float(@count)/Float(@total)) * 100.0)}% complete, #{@scores.size} records captured"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
file.close
|
77
|
+
end
|
78
|
+
|
79
|
+
def generate_flush_hand_rankings
|
80
|
+
file = File.new("7_card_flush_hands.csv", "w")
|
81
|
+
Suit.values().each do |suit|
|
82
|
+
generate_hand_rankings(suit, 6, 1, file)
|
83
|
+
generate_hand_rankings(suit, 7, 0, file)
|
84
|
+
end
|
85
|
+
file.close
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def generate_hand_rankings(suit, i, j, file)
|
91
|
+
Deck.new.retain_all(suit).combination(i).each do |suited|
|
92
|
+
Deck.new.remove_all(suit).combination(j).each do |remainder|
|
93
|
+
cards = suited + remainder
|
94
|
+
hand = get_best_hand(cards)
|
95
|
+
key = get_key(cards, hand)
|
96
|
+
if(!@scores.has_key?(key))
|
97
|
+
@scores[key] = hand.score
|
98
|
+
file.write("#{hand.score},#{key}")
|
99
|
+
end
|
100
|
+
@count = @count + 1
|
101
|
+
if(@count % 1000 == 0)
|
102
|
+
puts "#{DateTime.now.strftime('%Y-%m-%d %H:%M:%S')} :: #{@count} records processed, #{@scores.size} records captured"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def flush_count(suits, suit)
|
109
|
+
count = 0
|
110
|
+
suits.each do |s|
|
111
|
+
count = count + 1 if s.key == suit
|
112
|
+
end
|
113
|
+
count
|
114
|
+
end
|
115
|
+
|
116
|
+
def flush_suit(key)
|
117
|
+
return "H" if(key % HEART_FLUSH == 0)
|
118
|
+
return "D" if(key % DIAMOND_FLUSH == 0)
|
119
|
+
return "S" if(key % SPADE_FLUSH == 0)
|
120
|
+
return "C" if(key % CLUB_FLUSH == 0)
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_key(cards, hand)
|
124
|
+
cards.inject(1) {|product, card| product * (hand.flush? ? card.uid : card.rank.id) }
|
125
|
+
end
|
126
|
+
|
127
|
+
def ranks(cards)
|
128
|
+
cards.inject('') { |string, card| string << card.rank.key }
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_best_hand(cards)
|
132
|
+
cards.combination(5).to_a.each.collect { |selection| Hand.new(selection) }.sort {|x,y| x.score <=> y.score }[0]
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -7,19 +7,19 @@ class BoardTest < ActiveSupport::TestCase
|
|
7
7
|
end
|
8
8
|
|
9
9
|
test "should raise an error when a board is created with less than 3 cards" do
|
10
|
-
|
10
|
+
assert_raise_message "3 to 5 cards are required to create a board, 2 cards provided", ArgumentError do
|
11
11
|
Board.new "AS,KS"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
test "should raise an error when a board is created with more than 5 cards" do
|
16
|
-
|
16
|
+
assert_raise_message "3 to 5 cards are required to create a board, 6 cards provided", ArgumentError do
|
17
17
|
Board.new "AS,KS,QS,JS,TS,9S"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
test "should raise an error when a board is created with duplicate cards" do
|
22
|
-
|
22
|
+
assert_raise_message "The board contains duplicate cards", ArgumentError do
|
23
23
|
Board.new "AS KS JS AS KS"
|
24
24
|
end
|
25
25
|
end
|
@@ -30,8 +30,6 @@ class BoardTest < ActiveSupport::TestCase
|
|
30
30
|
|
31
31
|
test "the board should have three cards if the board was initialized with the flop" do
|
32
32
|
assert_equal 3, Board.new("AS,KS,QS").cards.size
|
33
|
-
b = Board.new("AS,KS,QS")
|
34
|
-
puts b.flop
|
35
33
|
end
|
36
34
|
|
37
35
|
test "the board should have four cards if the board was initialized with the flop and turn" do
|
@@ -43,20 +41,20 @@ class BoardTest < ActiveSupport::TestCase
|
|
43
41
|
end
|
44
42
|
|
45
43
|
test "should raise an error when a flop is not created with 3 cards" do
|
46
|
-
|
47
|
-
Board.new.flop "AS,KS"
|
44
|
+
assert_raise_message "3 cards are required on the flop, 2 cards provided", ArgumentError do
|
45
|
+
Board.new.flop= "AS,KS"
|
48
46
|
end
|
49
47
|
end
|
50
48
|
|
51
49
|
test "should raise an error when a flop is set with duplicate cards" do
|
52
|
-
|
53
|
-
Board.new.flop "AS AS JS"
|
50
|
+
assert_raise_message "The flop contains duplicate cards", ArgumentError do
|
51
|
+
Board.new.flop= "AS AS JS"
|
54
52
|
end
|
55
53
|
end
|
56
54
|
|
57
55
|
test "should raise an error when a flop is set with no cards" do
|
58
|
-
|
59
|
-
Board.new.flop []
|
56
|
+
assert_raise_message "Cannot deal a flop with empty array of cards", ArgumentError do
|
57
|
+
Board.new.flop= []
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
@@ -68,14 +66,14 @@ class BoardTest < ActiveSupport::TestCase
|
|
68
66
|
end
|
69
67
|
|
70
68
|
test "should raise an error when a turn card is dealt before the flop has been dealt" do
|
71
|
-
|
69
|
+
assert_raise_message "The flop must be dealt before the turn card is dealt", RuntimeError do
|
72
70
|
board = Board.new
|
73
71
|
board.turn = "AS"
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
77
|
-
test "should raise an error when the turn card has already been dealt" do
|
78
|
-
|
75
|
+
test "should raise an error when the turn card has already been dealt on the flop" do
|
76
|
+
assert_raise_message "The board already contains the Ace of Hearts", ArgumentError do
|
79
77
|
board = Board.new
|
80
78
|
board.flop= "AS,AH,AD"
|
81
79
|
board.turn= "AH"
|
@@ -91,15 +89,15 @@ class BoardTest < ActiveSupport::TestCase
|
|
91
89
|
end
|
92
90
|
|
93
91
|
test "should raise an error when the river card is dealt before the turn card has been dealt" do
|
94
|
-
|
92
|
+
assert_raise_message "The turn card must be dealt before the river card is dealt", RuntimeError do
|
95
93
|
board = Board.new
|
96
94
|
board.flop = "AS KS QS"
|
97
95
|
board.river = "JS"
|
98
96
|
end
|
99
97
|
end
|
100
98
|
|
101
|
-
test "should raise an error when the river card
|
102
|
-
|
99
|
+
test "should raise an error when the river card was dealt on a previous street" do
|
100
|
+
assert_raise_message "The board already contains the Ace of Spades", ArgumentError do
|
103
101
|
board = Board.new
|
104
102
|
board.flop = "AS,KS,QS"
|
105
103
|
board.turn = "JS"
|
@@ -121,9 +119,10 @@ class BoardTest < ActiveSupport::TestCase
|
|
121
119
|
assert_equal false, @board.contains?(Card.new("3D"))
|
122
120
|
end
|
123
121
|
|
124
|
-
test "should return true if the
|
125
|
-
|
126
|
-
assert_equal true,
|
122
|
+
test "should return true if the board contains the given card" do
|
123
|
+
b = Board.new "AS,KS,QS,JS,TS"
|
124
|
+
assert_equal true, b.contains?("TS")
|
125
|
+
assert_equal true, b.contains?(Card.new("AS"))
|
127
126
|
end
|
128
127
|
|
129
128
|
test "should return false if the board does not contain any of the given cards" do
|