rora 0.0.5
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/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
|