rora 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,86 @@
1
1
  #
2
- #
2
+ # A poker table where players compete for pots.
3
3
  #
4
4
  class Table
5
- attr_reader :board, :deck, :pot, :seats
5
+ attr_reader :board, :deck, :pot
6
6
 
7
7
  def initialize seats=nil
8
- @seats = Array.new(seats.nil? ? 9 : seats)
8
+ seats = seats.nil? ? 9 : seats
9
+ raise ArgumentError, "A table must have at least two seats" if seats < 2
10
+ @seats = Array.new seats
9
11
  @board = Board.new
10
12
  @pot = Pot.new
11
13
  @deck = Deck.new
14
+
15
+ @seats.each_index {|index| @seats[index] = Seat.new(index + 1)}
16
+ @seats.each_index do |index|
17
+ @seats[index].next = @seats[index == (seats - 1) ? 0 : index + 1]
18
+ @seats[index].prev = @seats[index == 0 ? seats - 1 : index - 1]
19
+ end
20
+ end
21
+
22
+ def pass_the_buck
23
+ index = the_button.number - 1
24
+ @seats[index].button = nil
25
+ the_seat_after(@seats[index]).button = true
26
+ end
27
+
28
+ def the_button
29
+ raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
30
+ @seats.each_index do |x|
31
+ return @seats[x] if @seats[x].button?
32
+ end
33
+ @seats.each_index do |x|
34
+ return @seats[x] if @seats[x].taken?
35
+ end
36
+ end
37
+
38
+ def the_small_blind
39
+ raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
40
+ players.size == 2 ? the_button : the_seat_after(the_button)
41
+ end
42
+
43
+ def the_big_blind
44
+ raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
45
+ the_seat_after the_small_blind
46
+ end
47
+
48
+ def under_the_gun
49
+ raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
50
+ the_seat_after(the_big_blind)
51
+ end
52
+
53
+ def the_seat_after seat
54
+ raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
55
+ this_seat = seat.next
56
+ return this_seat.taken? ? this_seat : the_seat_after(this_seat)
57
+ end
58
+
59
+ def the_seat_before seat
60
+ raise RuntimeError, "There are fewer than two players at the table" if players.size < 2
61
+ this_seat = seat.prev
62
+ return this_seat.taken? ? this_seat : the_seat_before(this_seat)
63
+ end
64
+
65
+ def with argument
66
+ if argument.kind_of? Deck
67
+ @deck = argument
68
+ end
69
+ if argument.kind_of? Pot
70
+ @pot = argument
71
+ end
72
+ if argument.kind_of? Board
73
+ @board = argument
74
+ end
75
+ self
76
+ end
77
+
78
+ def seat i
79
+ @seats[i - 1]
80
+ end
81
+
82
+ def size
83
+ @seats.size
12
84
  end
13
85
 
14
86
  def reset
@@ -17,24 +89,45 @@ class Table
17
89
  @deck = Deck.new
18
90
  end
19
91
 
92
+ def players
93
+ players = []
94
+ @seats.each do |seat|
95
+ players << seat.player if seat.taken?
96
+ end
97
+ players
98
+ end
99
+
100
+ def full?
101
+ @seats.select{|x| !x.taken?}.empty?
102
+ end
103
+
104
+ def empty?
105
+ @seats.select{|x| x.taken?}.empty?
106
+ end
107
+
20
108
  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
109
+ raise RuntimeError, "Cannot add player, the table is full" if full?
110
+ if !seat_number.nil?
111
+ raise ArgumentError, "Seat number #{seat_number} does not exist at this table" if seat_number > @seats.size || seat_number < 1
112
+ raise ArgumentError, "Seat number #{seat_number} is already taken by another player" if @seats[seat_number - 1].taken?
113
+ @seats[seat_number - 1].player = player
114
+ return self
115
+ end
116
+ @seats.each_index do |x|
117
+ if !@seats[x].taken?
118
+ @seats[x].player = player
119
+ return self
30
120
  end
31
121
  end
32
122
  self
33
123
  end
34
124
 
35
125
  def remove player
36
- @seats.delete player
37
- self
126
+ @seats.each_index do |x|
127
+ if @seats[x].player == player
128
+ @seats[x].player = nil
129
+ end
130
+ end
38
131
  end
39
132
 
40
133
  end
@@ -0,0 +1,19 @@
1
+ class GameLogger
2
+
3
+ def initialize
4
+ @log = Logger.new(STDOUT)
5
+ @log.sev_threshold = Logger::INFO
6
+ @log.formatter = proc do |severity, datetime, progname, msg|
7
+ "#{datetime}: #{msg}\n"
8
+ end
9
+ end
10
+
11
+ def debug message
12
+ @log.debug(message)
13
+ end
14
+
15
+ def info message
16
+ @log.info(message)
17
+ end
18
+
19
+ end
data/lib/rora.rb CHANGED
@@ -1,12 +1,17 @@
1
+ require 'rora/utils/game_logger'
1
2
  require 'rora/model/board'
2
3
  require 'rora/model/card'
3
4
  require 'rora/model/deck'
5
+ require 'rora/model/game'
4
6
  require 'rora/model/hand'
5
7
  require 'rora/model/hand_type'
8
+ require 'rora/model/player'
6
9
  require 'rora/model/pot'
7
10
  require 'rora/model/rank'
11
+ require 'rora/model/seat'
8
12
  require 'rora/model/starting_hand'
9
13
  require 'rora/model/suit'
10
-
14
+ require 'rora/model/table'
11
15
  require 'rora/repository/hand_repository'
12
- require 'rora/repository/starting_hand_repository'
16
+ require 'rora/repository/starting_hand_repository'
17
+ require 'logger'
@@ -2,6 +2,10 @@ require File.expand_path("../../rora_test", File.dirname(__FILE__))
2
2
 
3
3
  class BoardTest < ActiveSupport::TestCase
4
4
 
5
+ def setup
6
+ @board = Board.new "AS,KS,QS,JS,TS"
7
+ end
8
+
5
9
  test "should raise an error when a board is created with less than 3 cards" do
6
10
  assert_raise ArgumentError do
7
11
  Board.new "AS,KS"
@@ -26,6 +30,8 @@ class BoardTest < ActiveSupport::TestCase
26
30
 
27
31
  test "the board should have three cards if the board was initialized with the flop" do
28
32
  assert_equal 3, Board.new("AS,KS,QS").cards.size
33
+ b = Board.new("AS,KS,QS")
34
+ puts b.flop
29
35
  end
30
36
 
31
37
  test "the board should have four cards if the board was initialized with the flop and turn" do
@@ -111,27 +117,23 @@ class BoardTest < ActiveSupport::TestCase
111
117
  end
112
118
 
113
119
  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"))
120
+ assert_equal false, @board.contains?("3D")
121
+ assert_equal false, @board.contains?(Card.new("3D"))
117
122
  end
118
123
 
119
124
  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"))
125
+ assert_equal true, @board.contains?("TS")
126
+ assert_equal true, @board.contains?(Card.new("AS"))
123
127
  end
124
128
 
125
129
  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")
130
+ assert_equal false, @board.contains_any?(Card.to_cards("AH,KH,QH"))
131
+ assert_equal false, @board.contains_any?("AH,KH,QH")
129
132
  end
130
133
 
131
134
  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
+ assert_equal true, @board.contains_any?(Card.to_cards("AH,KH,QH,JH,KS"))
136
+ assert_equal true, @board.contains_any?("AH,KH,QH,JH,KS")
135
137
  end
136
138
 
137
139
  end
@@ -2,6 +2,10 @@ require File.expand_path("../../rora_test", File.dirname(__FILE__))
2
2
 
3
3
  class CardTest < ActiveSupport::TestCase
4
4
 
5
+ def setup
6
+ @card = Card.new("AS")
7
+ end
8
+
5
9
  test "should be able to create a card with the specified rank and suit" do
6
10
  card = Card.new(Rank::ACE, Suit::SPADE)
7
11
  assert_equal card.rank, Rank::ACE
@@ -18,20 +22,25 @@ class CardTest < ActiveSupport::TestCase
18
22
  assert_raise ArgumentError do
19
23
  card = Card.new("A")
20
24
  end
25
+ assert_raise ArgumentError do
26
+ card = Card.new("ASK")
27
+ end
28
+ end
29
+
30
+ test "a card should have an id" do
31
+ assert_equal 1927, @card.id
21
32
  end
22
33
 
23
34
  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)
35
+ assert_equal @card.id, (Rank::ACE.id * Suit::SPADE.id)
26
36
  end
27
37
 
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)
38
+ test "a card should have a key" do
39
+ assert_equal "AS", @card.key
31
40
  end
32
41
 
33
42
  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
43
+ assert_equal "AS", (Rank::ACE.key + Suit::SPADE.key)
35
44
  end
36
45
 
37
46
  test "a card should have a name" do
@@ -39,7 +48,7 @@ class CardTest < ActiveSupport::TestCase
39
48
  end
40
49
 
41
50
  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
51
+ assert_equal "Card: Ace of Spades", Card.new("AS").to_s
43
52
  end
44
53
 
45
54
  test "should convert an arbitrarily long string of characters into an array of cards" do
@@ -0,0 +1,23 @@
1
+ require File.expand_path("../../rora_test", File.dirname(__FILE__))
2
+
3
+ class GameTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @game = Game.new
7
+ end
8
+
9
+ test "play the game" do
10
+ for i in 0..5 do
11
+ player = Player.new("Player #{i}", 100000)
12
+ @game.add player
13
+ player.start_session
14
+ end
15
+
16
+ @game.shuffle_deck
17
+ @game.assign_button
18
+ @game.post_small_blind
19
+ @game.post_big_blind
20
+ @game.deal_pocket_cards
21
+ @game.run_preflop_betting_round
22
+ end
23
+ end
@@ -16,19 +16,19 @@ class HandTypeTest < ActiveSupport::TestCase
16
16
 
17
17
  test "should raise an error when performing a lookup with an invalid key" do
18
18
  assert_raise ArgumentError do
19
- HandType.get("L")
19
+ HandType.get "L"
20
20
  end
21
21
  end
22
22
 
23
23
  test "should raise an error when performing a lookup with an empty key" do
24
24
  assert_raise ArgumentError do
25
- HandType.get("")
25
+ HandType.get ""
26
26
  end
27
27
  end
28
28
 
29
29
  test "should raise an error when performing a lookup with a nil key" do
30
30
  assert_raise TypeError do
31
- HandType.get(nil)
31
+ HandType.get nil
32
32
  end
33
33
  end
34
34
 
@@ -0,0 +1,108 @@
1
+ require File.expand_path("../../rora_test", File.dirname(__FILE__))
2
+
3
+ class PlayerTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @game = Game.new
7
+ @player = Player.new "Frank", 100000
8
+ RSpec::Mocks::setup(self)
9
+ end
10
+
11
+ test "a player should have a name" do
12
+ assert_equal "foo", Player.new("foo", 999).name
13
+ end
14
+
15
+ test "a player should have a stack" do
16
+ assert_equal 1000, Player.new("feff", 1000).stack
17
+ end
18
+
19
+ test "should raise an error if the player name is nil" do
20
+ assert_raise_message "The player name cannot be nil", ArgumentError do
21
+ Player.new nil, 2000
22
+ end
23
+ end
24
+
25
+ test "a player should be able to join a poker game" do
26
+ @player.join_game @game
27
+ assert_equal @player, @game.table.seat(1).player
28
+ end
29
+
30
+ test "a player should be able to join a poker game at a seat of their choosing" do
31
+ @player.join_game @game, 3
32
+ assert_equal @player, @game.table.seat(3).player
33
+ end
34
+
35
+ test "a player should not be able to join a poker game when the poker table is full" do
36
+ @game.table.stub(:full?).and_return(true)
37
+ assert_raise_message "Frank cannot join this game, the table is full", ArgumentError do
38
+ @player.join_game @game
39
+ end
40
+ end
41
+
42
+ test "a player should not be able to join more than one game" do
43
+ @player.join_game @game
44
+ assert_raise_message "Frank cannot join this game, this player is already playing another game", ArgumentError do
45
+ @player.join_game @game
46
+ end
47
+ end
48
+
49
+ test "a player should not be able to start a session at a table if they do not have a seat at the table" do
50
+ assert_raise_message "Frank is not sitting at a table", ArgumentError do
51
+ @player.start_session
52
+ end
53
+ end
54
+
55
+ test "a player should be able to start a session at the poker table" do
56
+ @player.join_game @game
57
+ @player.start_session
58
+ assert_equal false, @player.sitting_out?
59
+ end
60
+
61
+ test "a player should be able to leave a game" do
62
+ @player.join_game @game
63
+ @player.start_session
64
+ @player.leave_game
65
+ assert_equal nil, @player.game
66
+ end
67
+
68
+ test "a player should not be able to post a small blind if the player has not joined a game" do
69
+ assert_raise_message "Frank has not joined a game, cannot post the small blind", ArgumentError do
70
+ @player.post_small_blind
71
+ end
72
+ end
73
+
74
+ test "a player should not be able to post a big blind if the player has not joined a game" do
75
+ assert_raise_message "Frank has not joined a game, cannot post the big blind", ArgumentError do
76
+ @player.post_big_blind
77
+ end
78
+ end
79
+
80
+ test "a player should not be able to post a small blind if the player is sitting out" do
81
+ @player.join_game @game
82
+ assert_raise_message "Frank is sitting out, cannot post the small blind", ArgumentError do
83
+ @player.post_small_blind
84
+ end
85
+ end
86
+
87
+ test "a player should not be able to post a big blind if the player is sitting out" do
88
+ @player.join_game @game
89
+ assert_raise_message "Frank is sitting out, cannot post the big blind", ArgumentError do
90
+ @player.post_big_blind
91
+ end
92
+ end
93
+
94
+ test "a player should be able to post a small blind" do
95
+ @player.join_game @game
96
+ @player.start_session
97
+ @player.post_small_blind
98
+ assert_equal 0.25, @game.pot.value
99
+ end
100
+
101
+ test "a player should be able to post a big blind" do
102
+ @player.join_game @game
103
+ @player.start_session
104
+ @player.post_big_blind
105
+ assert_equal 0.50, @game.pot.value
106
+ end
107
+
108
+ end
@@ -2,27 +2,34 @@ require File.expand_path("../../rora_test", File.dirname(__FILE__))
2
2
 
3
3
  class PotTest < ActiveSupport::TestCase
4
4
 
5
+ def setup
6
+ @pot = Pot.new
7
+ end
8
+
5
9
  test "a new post should have a total of 0 dollars" do
6
- assert_equal 0, Pot.new.total
10
+ assert_equal 0, @pot.value
11
+ end
12
+
13
+ test "should raise an error when attempting to add a negative value to the pot" do
14
+ assert_raise ArgumentError do
15
+ @pot.add -0.50
16
+ end
7
17
  end
8
18
 
9
19
  test "should be able to add money to the pot" do
10
- pot = Pot.new.add 5
11
- assert_equal 5, pot.total
20
+ assert_equal 5, @pot.add(5).value
12
21
  end
13
22
 
14
23
  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
24
+ assert_equal 5.75, @pot.add(5.75).value
17
25
  end
18
26
 
19
27
  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
28
+ assert_equal 6.25, @pot.add(2).add(2.25).add(2).value
22
29
  end
23
30
 
24
31
  test "should return a string representation of the pot" do
25
- assert_equal "Pot: $300.00", Pot.new().add(300.00).to_s
32
+ assert_equal "Pot: $300.00", @pot.add(300.00).to_s
26
33
  end
27
34
 
28
35
  end
@@ -21,25 +21,25 @@ class RankTest < ActiveSupport::TestCase
21
21
  end
22
22
 
23
23
  test "should raise an error when performing a lookup with an invalid key" do
24
- assert_raise ArgumentError do
25
- Rank.get("L")
24
+ assert_raise_message "No rank exists for key 'L'", ArgumentError do
25
+ Rank.get "L"
26
26
  end
27
27
  end
28
28
 
29
29
  test "should raise an error when performing a lookup with an empty key" do
30
- assert_raise ArgumentError do
31
- Rank.get("")
30
+ assert_raise_message "No rank exists for key ''", ArgumentError do
31
+ Rank.get ""
32
32
  end
33
33
  end
34
34
 
35
35
  test "should raise an error when performing a lookup with a nil key" do
36
36
  assert_raise TypeError do
37
- Rank.get(nil)
37
+ Rank.get nil
38
38
  end
39
39
  end
40
40
 
41
41
  test "should generate a readable string representation" do
42
- assert_equal "Rank: id=41, key='A', value='Ace'", Rank::ACE.to_s
42
+ assert_equal "Rank: Ace", Rank::ACE.to_s
43
43
  end
44
44
 
45
45
  end
@@ -0,0 +1,41 @@
1
+ require File.expand_path("../../rora_test", File.dirname(__FILE__))
2
+
3
+ class SeatTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @seat = Seat.new 2
7
+ end
8
+
9
+ test "should raise an error when a seat is created with a seat number less than 1" do
10
+ assert_raise ArgumentError do
11
+ Seat.new 0
12
+ end
13
+ end
14
+
15
+ test "the seat should have a seat number" do
16
+ assert_equal 2, @seat.number
17
+ end
18
+
19
+ test "the seat should not be taken when a player is not sitting in it" do
20
+ assert_equal false, @seat.taken?
21
+ end
22
+
23
+ test "the seat should be taken when a player is sitting in it" do
24
+ @seat.player = "player"
25
+ assert_equal true, @seat.taken?
26
+ end
27
+
28
+ test "the seat should not have the dealer button" do
29
+ assert_equal false, @seat.button?
30
+ end
31
+
32
+ test "the seat should have the dealer button" do
33
+ @seat.button = true
34
+ assert_equal true, @seat.button?
35
+ end
36
+
37
+ test "should return a string representation of the seat" do
38
+ assert_equal "Seat: 2", @seat.to_s
39
+ end
40
+
41
+ end
@@ -39,7 +39,7 @@ class SuitTest < ActiveSupport::TestCase
39
39
  end
40
40
 
41
41
  test "should generate a readable string representation" do
42
- assert_equal "Suit: id=47, key='S', value='Spade'", Suit::SPADE.to_s
42
+ assert_equal "Suit: Spades", Suit::SPADE.to_s
43
43
  end
44
44
 
45
45
  end