rora 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +17 -0
- data/README.md +258 -0
- data/Rakefile +12 -0
- data/lib/rora/hands.csv +7462 -0
- data/lib/rora/model/board.rb +95 -0
- data/lib/rora/model/card.rb +74 -0
- data/lib/rora/model/deck.rb +109 -0
- data/lib/rora/model/game.rb +8 -0
- data/lib/rora/model/hand.rb +126 -0
- data/lib/rora/model/hand_type.rb +53 -0
- data/lib/rora/model/player.rb +8 -0
- data/lib/rora/model/pot.rb +21 -0
- data/lib/rora/model/rank.rb +52 -0
- data/lib/rora/model/starting_hand.rb +102 -0
- data/lib/rora/model/suit.rb +43 -0
- data/lib/rora/model/table.rb +40 -0
- data/lib/rora/repository/hand_repository.rb +133 -0
- data/lib/rora/repository/starting_hand_repository.rb +23 -0
- data/lib/rora.rb +12 -0
- data/test/rora/model/board_test.rb +137 -0
- data/test/rora/model/card_test.rb +57 -0
- data/test/rora/model/deck_test.rb +114 -0
- data/test/rora/model/hand_test.rb +91 -0
- data/test/rora/model/hand_type_test.rb +39 -0
- data/test/rora/model/pot_test.rb +28 -0
- data/test/rora/model/rank_test.rb +45 -0
- data/test/rora/model/starting_hand_test.rb +71 -0
- data/test/rora/model/suit_test.rb +45 -0
- data/test/rora/repository/hand_repository_test.rb +83 -0
- data/test/rora/repository/starting_hand_repository_test.rb +17 -0
- data/test/rora_test.rb +5 -0
- metadata +119 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
#
|
3
|
+
#
|
4
|
+
class Table
|
5
|
+
attr_reader :board, :deck, :pot, :seats
|
6
|
+
|
7
|
+
def initialize seats=nil
|
8
|
+
@seats = Array.new(seats.nil? ? 9 : seats)
|
9
|
+
@board = Board.new
|
10
|
+
@pot = Pot.new
|
11
|
+
@deck = Deck.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
@board = Board.new
|
16
|
+
@pot = Pot.new
|
17
|
+
@deck = Deck.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def add player, seat_number=nil
|
21
|
+
if !location.nil?
|
22
|
+
raise ArgumentException, "Seat #{seat_number} is already taken by another player." if @seats[seat_number - 1] != nil
|
23
|
+
@seats[seat_number - 1] = player
|
24
|
+
else
|
25
|
+
@seats.each_index do |x|
|
26
|
+
if @seats[x].nil?
|
27
|
+
@seats[x] = player
|
28
|
+
return
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove player
|
36
|
+
@seats.delete player
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
class HandRepository
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@hands = Array.new
|
9
|
+
@table = Hash.new
|
10
|
+
CSV.foreach("lib/rora/hands.csv") do |row|
|
11
|
+
@table[row[1].to_i] = [row[0].to_i, row[3], row[4], row[5].to_f]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def find id
|
16
|
+
@table.fetch id
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns all possible poker hands.
|
20
|
+
#
|
21
|
+
# No Arguments
|
22
|
+
# If no arguments are provided, this method will return all
|
23
|
+
# 2,598,960 (52c5) poker hands.
|
24
|
+
#
|
25
|
+
# Starting Hand
|
26
|
+
# If a starting hand is provided as an argument, this method returns all
|
27
|
+
# poker hands that can be made with the given starting hand. A standard
|
28
|
+
# deck of 52 cards is assumed. Exactly 19,600 (50c3) 5-card poker hands
|
29
|
+
# will be returned for any given starting hand.
|
30
|
+
#
|
31
|
+
# Starting Hand and Deck
|
32
|
+
# If a deck is provided along with a starting hand, this method will return
|
33
|
+
# all poker hands that can be made with the given starting hand and cards
|
34
|
+
# that remain in the deck.
|
35
|
+
#
|
36
|
+
# Starting Hand and Board
|
37
|
+
# If a board is provided along with a starting hand, this method will return
|
38
|
+
# all poker hands that can be made with the given starting hand and board. In
|
39
|
+
# this scenario, a standard deck of 52 cards is assumed. A deck will contain
|
40
|
+
# exactly 50 cards after the starting hand has been dealt. The deck will contain
|
41
|
+
# 47 cards after the flop, 46 cards after the turn and 45 cards after the river.
|
42
|
+
#
|
43
|
+
# Once the community cards have been dealt, there are 21 (7c5) ways to
|
44
|
+
# choose a 5-card poker hand from the 5 community cards and 2 hole cards.
|
45
|
+
# The total number of hands that will be returned from this method are as
|
46
|
+
# follows:
|
47
|
+
#
|
48
|
+
# If the board has 5 community cards, flop turn & river have been
|
49
|
+
# dealt:
|
50
|
+
# 21 hands -> 21 (7c5) # 1 (45c0)
|
51
|
+
#
|
52
|
+
# If the board has 4 community cards, flop and turn have been dealt:
|
53
|
+
# 966 hands -> 21 (7c5) # 46 (46c1)
|
54
|
+
#
|
55
|
+
# If the board has 3 community cards, flop has been dealt:
|
56
|
+
# 22701 hands -> 21 (7c5) # 1081 (47c2)
|
57
|
+
#
|
58
|
+
# Starting Hand, Board and Deck
|
59
|
+
# This method will return all poker hands that can be made with the given starting
|
60
|
+
# hand and cards that remain in the deck.
|
61
|
+
def list arguments=nil
|
62
|
+
return hands if arguments.nil? || arguments[:starting_hand].nil?
|
63
|
+
|
64
|
+
starting_hand = arguments[:starting_hand]
|
65
|
+
deck = arguments[:deck].nil? ? Deck.new : arguments[:deck]
|
66
|
+
board = arguments[:board]
|
67
|
+
hands = Array.new
|
68
|
+
|
69
|
+
if !board.nil?
|
70
|
+
raise RuntimeError if board.contains_any? starting_hand.cards
|
71
|
+
if board.cards.size == 5
|
72
|
+
(board.cards + starting_hand.cards).combination(5).to_a.each { |cards| hands << Hand.new(cards) }
|
73
|
+
return hands
|
74
|
+
else
|
75
|
+
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| hands << Hand.new(cds) }
|
77
|
+
end
|
78
|
+
return hands
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
deck.remove(starting_hand).combination(3).each { |cards| hands << Hand.new(cards + starting_hand.cards) }
|
83
|
+
hands
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns unique poker hands.
|
87
|
+
#
|
88
|
+
# While there are over 2.5 million distinct poker hands, many of these hands have the same
|
89
|
+
# value in poker. To elaborate on this a bit, consider the number of hands a player could have
|
90
|
+
# containing a pair of fours with a 10-7-6 kicker:
|
91
|
+
#
|
92
|
+
# 4♣ 4♦ 6♠ 7♥ 10♥
|
93
|
+
# 4♠ 4♦ 6♠ 7♥ 10♥
|
94
|
+
# 4♥ 4♦ 6♠ 7♥ 10♥
|
95
|
+
# 4♣ 4♠ 6♠ 7♥ 10♥
|
96
|
+
# 4♣ 4♦ 6♠ 7♥ 10♦
|
97
|
+
# 4♣ 4♦ 6♠ 7♦ 10♥
|
98
|
+
# 4♣ 4♦ 6♣ 7♥ 10♥
|
99
|
+
# 4♣ 4♦ 6♠ 7♠ 10♥
|
100
|
+
# 4♣ 4♦ 6♠ 7♦ 10♠
|
101
|
+
# 4♣ 4♦ 6♣ 7♥ 10♣
|
102
|
+
#
|
103
|
+
# This list goes on much further - in fact, there are exactly 768 distinct hand combinations that
|
104
|
+
# contain of exactly one pair of fours with a 10-7-6 kicker. Each of these 768 hands has the same
|
105
|
+
# hand value, or score.
|
106
|
+
#
|
107
|
+
# This exercise demonstrates that the number of unique hands (that is, hands that share an identical
|
108
|
+
# hand score) is significantly lower than the number of distinct hands. This is because card suits
|
109
|
+
# don’t tend to affect the score of a hand (the only exception being a flush).
|
110
|
+
#
|
111
|
+
# This method carries the same semantics as the list method, but returns unique hands instead of
|
112
|
+
# every possible hand.
|
113
|
+
def list_unique arguments=nil
|
114
|
+
results = list arguments
|
115
|
+
return results if results.nil? || results.size == 0
|
116
|
+
|
117
|
+
hash = Hash.new
|
118
|
+
results.each do |result|
|
119
|
+
hash[result.hash_key] = result
|
120
|
+
end
|
121
|
+
hash.values
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def hands
|
127
|
+
if @hands.empty?
|
128
|
+
Deck.new.combination(5).each {|cards| @hands << Hand.new(cards)}
|
129
|
+
end
|
130
|
+
@hands
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class StartingHandRepository
|
2
|
+
include Singleton
|
3
|
+
attr_reader :all, :distinct
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@all = Array.new
|
7
|
+
@distinct = Hash.new
|
8
|
+
Deck.new.cards.combination(2) do |combination|
|
9
|
+
starting_hand = StartingHand.new(combination)
|
10
|
+
@all << starting_hand
|
11
|
+
@distinct[starting_hand.key] = starting_hand
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def all_starting_hands
|
16
|
+
@all
|
17
|
+
end
|
18
|
+
|
19
|
+
def distinct_starting_hands
|
20
|
+
@distinct.values
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/rora.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rora/model/board'
|
2
|
+
require 'rora/model/card'
|
3
|
+
require 'rora/model/deck'
|
4
|
+
require 'rora/model/hand'
|
5
|
+
require 'rora/model/hand_type'
|
6
|
+
require 'rora/model/pot'
|
7
|
+
require 'rora/model/rank'
|
8
|
+
require 'rora/model/starting_hand'
|
9
|
+
require 'rora/model/suit'
|
10
|
+
|
11
|
+
require 'rora/repository/hand_repository'
|
12
|
+
require 'rora/repository/starting_hand_repository'
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require File.expand_path("../../rora_test", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class BoardTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "should raise an error when a board is created with less than 3 cards" do
|
6
|
+
assert_raise ArgumentError do
|
7
|
+
Board.new "AS,KS"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
test "should raise an error when a board is created with more than 5 cards" do
|
12
|
+
assert_raise ArgumentError do
|
13
|
+
Board.new "AS,KS,QS,JS,TS,9S"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should raise an error when a board is created with duplicate cards" do
|
18
|
+
assert_raise ArgumentError do
|
19
|
+
Board.new "AS KS JS AS KS"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test "should have an empty board if the board was not initialized with cards" do
|
24
|
+
assert_equal 0, Board.new.cards.size
|
25
|
+
end
|
26
|
+
|
27
|
+
test "the board should have three cards if the board was initialized with the flop" do
|
28
|
+
assert_equal 3, Board.new("AS,KS,QS").cards.size
|
29
|
+
end
|
30
|
+
|
31
|
+
test "the board should have four cards if the board was initialized with the flop and turn" do
|
32
|
+
assert_equal 4, Board.new("AS,KS,QS,JS").cards.size
|
33
|
+
end
|
34
|
+
|
35
|
+
test "the board should have five cards if the board was initialized with the flop, turn and river" do
|
36
|
+
assert_equal 5, Board.new("AS,KS,QS,JS,TS").cards.size
|
37
|
+
end
|
38
|
+
|
39
|
+
test "should raise an error when a flop is not created with 3 cards" do
|
40
|
+
assert_raise ArgumentError do
|
41
|
+
Board.new.flop "AS,KS"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
test "should raise an error when a flop is set with duplicate cards" do
|
46
|
+
assert_raise ArgumentError do
|
47
|
+
Board.new.flop "AS AS JS"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test "should raise an error when a flop is set with no cards" do
|
52
|
+
assert_raise ArgumentError do
|
53
|
+
Board.new.flop []
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
test "should have a board with three cards after the flop is dealt" do
|
58
|
+
board = Board.new
|
59
|
+
board.flop = "AS KS QS"
|
60
|
+
assert_equal 3, board.cards.size
|
61
|
+
assert_equal board.flop, board.cards
|
62
|
+
end
|
63
|
+
|
64
|
+
test "should raise an error when a turn card is dealt before the flop has been dealt" do
|
65
|
+
assert_raise RuntimeError do
|
66
|
+
board = Board.new
|
67
|
+
board.turn = "AS"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
test "should raise an error when the turn card has already been dealt" do
|
72
|
+
assert_raise ArgumentError do
|
73
|
+
board = Board.new
|
74
|
+
board.flop= "AS,AH,AD"
|
75
|
+
board.turn= "AH"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
test "should have a board with four cards after the turn card is dealt" do
|
80
|
+
board = Board.new
|
81
|
+
board.flop = "AS KS QS"
|
82
|
+
board.turn = "JS"
|
83
|
+
assert_equal 4, board.cards.size
|
84
|
+
assert_equal Card.new("JS"), board.turn
|
85
|
+
end
|
86
|
+
|
87
|
+
test "should raise an error when the river card is dealt before the turn card has been dealt" do
|
88
|
+
assert_raise RuntimeError do
|
89
|
+
board = Board.new
|
90
|
+
board.flop = "AS KS QS"
|
91
|
+
board.river = "JS"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
test "should raise an error when the river card has already been dealt" do
|
96
|
+
assert_raise ArgumentError do
|
97
|
+
board = Board.new
|
98
|
+
board.flop = "AS,KS,QS"
|
99
|
+
board.turn = "JS"
|
100
|
+
board.river = "AS"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
test "should have a board with five cards after the river card is dealt" do
|
105
|
+
board = Board.new
|
106
|
+
board.flop = "AS KS QS"
|
107
|
+
board.turn = "JS"
|
108
|
+
board.river = "TS"
|
109
|
+
assert_equal 5, board.cards.size
|
110
|
+
assert_equal Card.new("TS"), board.river
|
111
|
+
end
|
112
|
+
|
113
|
+
test "should return false if the board does not contain the given card" do
|
114
|
+
board = Board.new "AS,KS,QS,JS,TS"
|
115
|
+
assert_equal false, board.contains?("3D")
|
116
|
+
assert_equal false, board.contains?(Card.new("3D"))
|
117
|
+
end
|
118
|
+
|
119
|
+
test "should return true if the boad does contain the given card" do
|
120
|
+
board = Board.new "AS,KS,QS,JS,TS"
|
121
|
+
assert_equal true, board.contains?("TS")
|
122
|
+
assert_equal true, board.contains?(Card.new("AS"))
|
123
|
+
end
|
124
|
+
|
125
|
+
test "should return false if the board does not contain any of the given cards" do
|
126
|
+
board = Board.new "AS,KS,QS,JS,TS"
|
127
|
+
assert_equal false, board.contains_any?(Card.to_cards("AH,KH,QH"))
|
128
|
+
assert_equal false, board.contains_any?("AH,KH,QH")
|
129
|
+
end
|
130
|
+
|
131
|
+
test "should return true if the board contains at least one of the given cards" do
|
132
|
+
board = Board.new "AS,KS,QS,JS,TS"
|
133
|
+
assert_equal true, board.contains_any?(Card.to_cards("AH,KH,QH,JH,KS"))
|
134
|
+
assert_equal true, board.contains_any?("AH,KH,QH,JH,KS")
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path("../../rora_test", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class CardTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "should be able to create a card with the specified rank and suit" do
|
6
|
+
card = Card.new(Rank::ACE, Suit::SPADE)
|
7
|
+
assert_equal card.rank, Rank::ACE
|
8
|
+
assert_equal card.suit, Suit::SPADE
|
9
|
+
end
|
10
|
+
|
11
|
+
test "should be able to create a card with the specified string value" do
|
12
|
+
card = Card.new("AS")
|
13
|
+
assert_equal card.rank, Rank::ACE
|
14
|
+
assert_equal card.suit, Suit::SPADE
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should raise an exception when attempting to create a card with an invalid string value" do
|
18
|
+
assert_raise ArgumentError do
|
19
|
+
card = Card.new("A")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test "a card id should be equal to the product of the card suit id and rank id" do
|
24
|
+
card = Card.new(Rank::ACE, Suit::SPADE)
|
25
|
+
assert_equal card.id, (Rank::ACE.id * Suit::SPADE.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
test "a card value should be equal to the concatenation of the card suit value and rank value" do
|
29
|
+
card = Card.new(Rank::ACE, Suit::SPADE)
|
30
|
+
assert_equal card.value, (Rank::ACE.value + Suit::SPADE.value)
|
31
|
+
end
|
32
|
+
|
33
|
+
test "a card key should be equal to the concatenation of the card suit key and rank key" do
|
34
|
+
assert_equal "AS", Card.new("AS").key
|
35
|
+
end
|
36
|
+
|
37
|
+
test "a card should have a name" do
|
38
|
+
assert_equal "Ace of Spades", Card.new("AS").name
|
39
|
+
end
|
40
|
+
|
41
|
+
test "should generate a readable string representation" do
|
42
|
+
assert_equal "Card: name='Ace of Spades' value='AS' id=1927", Card.new("AS").to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
test "should convert an arbitrarily long string of characters into an array of cards" do
|
46
|
+
assert_equal 7, Card.to_cards("ASKSJSQSTCJCAH").size
|
47
|
+
end
|
48
|
+
|
49
|
+
test "should convert an arbitrarily long string of comma-delimited characters into an array of cards" do
|
50
|
+
assert_equal 7, Card.to_cards("AS,KS,JS,QS,TC,JC,AH").size
|
51
|
+
end
|
52
|
+
|
53
|
+
test "should convert an arbitrarily long string of space-delimited characters into an array of cards" do
|
54
|
+
assert_equal 7, Card.to_cards("AS KS JS QS TC JC AH").size
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require File.expand_path("../../rora_test", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class DeckTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@deck = Deck.new
|
7
|
+
@card = Card.new("AS")
|
8
|
+
end
|
9
|
+
|
10
|
+
test "a deck should contain 52 cards" do
|
11
|
+
assert_equal 52, @deck.size
|
12
|
+
end
|
13
|
+
|
14
|
+
test "a deck should not be empty" do
|
15
|
+
assert_equal false, @deck.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
test "a deck should be empty after all 52 cards have been dealt" do
|
19
|
+
52.times { @deck.deal }
|
20
|
+
assert_equal true, @deck.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
test "a deck should contain 4 cards of each rank" do
|
24
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::ACE)
|
25
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::KING)
|
26
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::QUEEN)
|
27
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::JACK)
|
28
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::TEN)
|
29
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::NINE)
|
30
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::EIGHT)
|
31
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::SEVEN)
|
32
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::SIX)
|
33
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::FIVE)
|
34
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::FOUR)
|
35
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::THREE)
|
36
|
+
assert_equal 4, @deck.count_cards_with_rank(Rank::TWO)
|
37
|
+
end
|
38
|
+
|
39
|
+
test "a deck should contain 13 cards of each suit" do
|
40
|
+
assert_equal 13, @deck.count_cards_with_suit(Suit::CLUB)
|
41
|
+
assert_equal 13, @deck.count_cards_with_suit(Suit::DIAMOND)
|
42
|
+
assert_equal 13, @deck.count_cards_with_suit(Suit::HEART)
|
43
|
+
assert_equal 13, @deck.count_cards_with_suit(Suit::SPADE)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "should return a shallow copy of cards" do
|
47
|
+
assert_equal 52, @deck.size
|
48
|
+
@deck.cards.delete_at(0)
|
49
|
+
assert_equal 52, @deck.size
|
50
|
+
end
|
51
|
+
|
52
|
+
test "should shuffle the cards in a deck" do
|
53
|
+
before = @deck.cards[0]
|
54
|
+
@deck.shuffle
|
55
|
+
after = @deck.cards[0]
|
56
|
+
assert_not_equal before, after
|
57
|
+
end
|
58
|
+
|
59
|
+
test "should remove a card from the deck" do
|
60
|
+
assert_equal 52, @deck.size
|
61
|
+
@deck.remove @card
|
62
|
+
assert_equal 51, @deck.size
|
63
|
+
@deck.remove @card
|
64
|
+
assert_equal 51, @deck.size
|
65
|
+
end
|
66
|
+
|
67
|
+
test "should remove multiple cards from the deck" do
|
68
|
+
cards = [Card.new("QS"), Card.new("KS"), Card.new("AS")]
|
69
|
+
|
70
|
+
assert_equal 52, @deck.size
|
71
|
+
@deck.remove cards
|
72
|
+
assert_equal 49, @deck.size
|
73
|
+
@deck.remove cards
|
74
|
+
assert_equal 49, @deck.size
|
75
|
+
end
|
76
|
+
|
77
|
+
test "should remove a starting hand from the deck" do
|
78
|
+
assert_equal 52, @deck.size
|
79
|
+
@deck.remove StartingHand.new("ASKS")
|
80
|
+
assert_equal 50, @deck.size
|
81
|
+
end
|
82
|
+
|
83
|
+
test "should remove card values from the deck" do
|
84
|
+
assert_equal 52, @deck.size
|
85
|
+
@deck.remove "AS"
|
86
|
+
assert_equal 51, @deck.size
|
87
|
+
@deck.remove "KS,QS"
|
88
|
+
assert_equal 49, @deck.size
|
89
|
+
end
|
90
|
+
|
91
|
+
test "should determine if the given card is in the deck" do
|
92
|
+
assert_equal true, @deck.contains?(@card)
|
93
|
+
@deck.remove(@card)
|
94
|
+
assert_equal false, @deck.contains?(@card)
|
95
|
+
end
|
96
|
+
|
97
|
+
test "should deal a card from the deck" do
|
98
|
+
card = @deck.deal
|
99
|
+
assert_not_nil card
|
100
|
+
assert_equal 51, @deck.size
|
101
|
+
end
|
102
|
+
|
103
|
+
test "should return false if the board does not contain any of the given cards" do
|
104
|
+
@deck.remove "AH,KH,QH,JS,TS"
|
105
|
+
assert_equal false, @deck.contains_any?(Card.to_cards("AH,KH,QH"))
|
106
|
+
assert_equal false, @deck.contains_any?("AH,KH,QH")
|
107
|
+
end
|
108
|
+
|
109
|
+
test "should return true if the board contains at least one of the given cards" do
|
110
|
+
assert_equal true, @deck.contains_any?(Card.to_cards("AH,KH,QH,JH,KS"))
|
111
|
+
assert_equal true, @deck.contains_any?("AH,KH,QH,JH,KS")
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path("../../rora_test", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class HandTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@hand = Hand.new("AS,KS,QS,JS,TS")
|
7
|
+
end
|
8
|
+
|
9
|
+
test "should raise an error when a hand is not created with 5 cards" do
|
10
|
+
assert_raise ArgumentError do
|
11
|
+
Hand.new [Card.new("AS"), Card.new("KS")]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should raise an error when a hand is not created with 10 characters" do
|
16
|
+
assert_raise ArgumentError do
|
17
|
+
Hand.new "ASKSQSJS"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test "should raise an error when creating a hand with duplicate cards" do
|
22
|
+
assert_raise ArgumentError do
|
23
|
+
Hand.new "AS KS JS AS KS"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
test "the hand should have an id" do
|
28
|
+
assert_equal 7193866898674063, @hand.id
|
29
|
+
end
|
30
|
+
|
31
|
+
test "the hand id should be equal to the product of each card id contained in the hand" do
|
32
|
+
assert_equal @hand.id, (Card.new("AS").id * Card.new("KS").id * Card.new("QS").id * Card.new("JS").id * Card.new("TS").id)
|
33
|
+
end
|
34
|
+
|
35
|
+
test "the hand should have a hash key" do
|
36
|
+
assert_equal 2101589603, @hand.hash_key
|
37
|
+
end
|
38
|
+
|
39
|
+
test "the hash key should be equal to the product of each card rank id in the hand times" do
|
40
|
+
assert_equal Hand.new("ASACAHJSTS").hash_key, (Card.new("AS").rank.id * Card.new("AC").rank.id * Card.new("AH").rank.id * Card.new("JS").rank.id * Card.new("TS").rank.id)
|
41
|
+
end
|
42
|
+
|
43
|
+
test "the hash key should be equal to the product of each card rank id in the hand times 67 when the hand is a flush" do
|
44
|
+
assert_equal @hand.hash_key, (Card.new("AS").rank.id * Card.new("KS").rank.id * Card.new("QS").rank.id * Card.new("JS").rank.id * Card.new("TS").rank.id * 67)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "the hand should have a value" do
|
48
|
+
assert_equal "AS,KS,QS,JS,TS", @hand.value
|
49
|
+
end
|
50
|
+
|
51
|
+
test "the hand should be a flush" do
|
52
|
+
assert_equal true, @hand.flush?
|
53
|
+
end
|
54
|
+
|
55
|
+
test "the hand should not be a flush" do
|
56
|
+
assert_equal false, Hand.new("2D3S4H8CJS").flush?
|
57
|
+
end
|
58
|
+
|
59
|
+
test "the hand should have a score" do
|
60
|
+
assert_equal 1, @hand.score
|
61
|
+
end
|
62
|
+
|
63
|
+
test "the hand should have a probability" do
|
64
|
+
assert_equal 0.0015, @hand.probability
|
65
|
+
end
|
66
|
+
|
67
|
+
test "the hand should have a name" do
|
68
|
+
assert_equal "Royal Flush", @hand.name
|
69
|
+
end
|
70
|
+
|
71
|
+
test "the hand should have a hand type" do
|
72
|
+
assert_equal HandType::STRAIGHT_FLUSH, @hand.type
|
73
|
+
end
|
74
|
+
|
75
|
+
test "the hand should have five cards" do
|
76
|
+
assert_equal 5, @hand.cards.size
|
77
|
+
end
|
78
|
+
|
79
|
+
test "the hand should be a straight flush" do
|
80
|
+
assert_equal true, @hand.straight_flush?
|
81
|
+
end
|
82
|
+
|
83
|
+
test "the hand should be a straight" do
|
84
|
+
assert_equal true, Hand.new("ACKSQSJDTS").straight?
|
85
|
+
end
|
86
|
+
|
87
|
+
test "the hand should be a four of a kind" do
|
88
|
+
assert_equal true, Hand.new("ACASAHADJS").four_of_a_kind?
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path("../../rora_test", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class HandTypeTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "should return all hand types" do
|
6
|
+
assert_equal 9, HandType.values.size
|
7
|
+
end
|
8
|
+
|
9
|
+
test "should return the correct hand type for the given key" do
|
10
|
+
assert_equal HandType::HIGH_CARD, HandType.get("HC")
|
11
|
+
end
|
12
|
+
|
13
|
+
test "should perform a case insensitive key lookup" do
|
14
|
+
assert_equal(HandType::HIGH_CARD, HandType.get("Hc"))
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should raise an error when performing a lookup with an invalid key" do
|
18
|
+
assert_raise ArgumentError do
|
19
|
+
HandType.get("L")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test "should raise an error when performing a lookup with an empty key" do
|
24
|
+
assert_raise ArgumentError do
|
25
|
+
HandType.get("")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
test "should raise an error when performing a lookup with a nil key" do
|
30
|
+
assert_raise TypeError do
|
31
|
+
HandType.get(nil)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
test "should generate a readable string representation" do
|
36
|
+
assert_equal "HandType: key='FL', value='Flush'", HandType::FLUSH.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path("../../rora_test", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PotTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "a new post should have a total of 0 dollars" do
|
6
|
+
assert_equal 0, Pot.new.total
|
7
|
+
end
|
8
|
+
|
9
|
+
test "should be able to add money to the pot" do
|
10
|
+
pot = Pot.new.add 5
|
11
|
+
assert_equal 5, pot.total
|
12
|
+
end
|
13
|
+
|
14
|
+
test "should be able to add money with decimals to the pot" do
|
15
|
+
pot = Pot.new.add 5.75
|
16
|
+
assert_equal 5.75, pot.total
|
17
|
+
end
|
18
|
+
|
19
|
+
test "should be able to perform compound addtion operations" do
|
20
|
+
pot = Pot.new.add(2).add(2.25).add(2)
|
21
|
+
assert_equal 6.25, pot.total
|
22
|
+
end
|
23
|
+
|
24
|
+
test "should return a string representation of the pot" do
|
25
|
+
assert_equal "Pot: $300.00", Pot.new().add(300.00).to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|