acpc_dealer_data 0.3.3 → 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a1b82be7131e77192adfdf5cc580289a1f85facf
4
+ data.tar.gz: 97cd0e6a637586fd999c83e47d27c7516386fdde
5
+ SHA512:
6
+ metadata.gz: 74054e4d315506f413864776bdf18df98e27093c1e401ce536971a6977672ddaa0b9e4272b2de09ff9cdacd09ef53326de18266d60994fe65955e45bc6d48f55
7
+ data.tar.gz: 84fb2b82c348817ae76794e5864e1339af37dea0794bb25493de65fcfc29613c7a146ddc7f55dc287b05946a7ee27241f08f474fa2081fb3ec4757996b1b4aff
data/Rakefile CHANGED
@@ -7,6 +7,6 @@ require 'rake/testtask'
7
7
  Rake::TestTask.new do |t|
8
8
  t.libs << "lib" << 'spec/support'
9
9
  t.test_files = FileList['spec/**/*_spec.rb']
10
- t.verbose = true
11
- t.warning = true
10
+ t.verbose = false
11
+ t.warning = false # pry-rescue has a lot of warnings
12
12
  end
@@ -8,15 +8,17 @@ Gem::Specification.new do |gem|
8
8
  gem.summary = %q{Gem to parse, manipulate, and use data from the ACPC Dealer program.}
9
9
  gem.homepage = "https://github.com/dmorrill10/acpc_dealer_data"
10
10
 
11
- gem.add_dependency 'acpc_dealer'
12
- gem.add_dependency 'acpc_poker_types'
13
- gem.add_dependency 'celluloid'
14
- gem.add_dependency 'dmorrill10-utils', '>=1.0.0'
11
+ gem.add_dependency 'acpc_dealer', '~> 0.0'
12
+ gem.add_dependency 'acpc_poker_types', '~> 0.0'
13
+ gem.add_dependency 'celluloid', '~> 0.13'
14
+ gem.add_dependency 'dmorrill10-utils', '~> 1.0'
15
15
 
16
-
17
- gem.add_development_dependency 'mocha'
18
- gem.add_development_dependency 'simplecov'
19
- gem.add_development_dependency 'turn'
16
+ gem.add_development_dependency 'minitest', '~> 4.7'
17
+ gem.add_development_dependency 'mocha', '~> 0.13'
18
+ gem.add_development_dependency 'simplecov', '~> 0.7'
19
+ gem.add_development_dependency 'turn', '~> 0.9'
20
+ gem.add_development_dependency 'pry-rescue', '~> 1.1'
21
+ gem.add_development_dependency 'awesome_print', '~> 1.1'
20
22
 
21
23
  gem.files = `git ls-files`.split($\)
22
24
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -5,6 +5,7 @@ require 'acpc_dealer_data/hand_data'
5
5
  require 'acpc_dealer_data/hand_results'
6
6
  require 'acpc_dealer_data/poker_match_data'
7
7
  require 'acpc_dealer_data/match_definition'
8
+ require 'acpc_dealer_data/log_file'
8
9
 
9
10
  module AcpcDealerData
10
11
  end
@@ -2,14 +2,14 @@
2
2
  require 'acpc_poker_types/match_state'
3
3
  require 'acpc_poker_types/poker_action'
4
4
 
5
- require_relative 'match_definition'
6
-
7
- class ActionMessages
5
+ require 'acpc_dealer_data/match_definition'
6
+ require 'acpc_dealer_data/log_file'
8
7
 
8
+ class AcpcDealerData::ActionMessages
9
9
  attr_reader(
10
10
  :data, :final_score, :match_def
11
11
  )
12
-
12
+
13
13
  ToMessage = Struct.new(
14
14
  # @returns [Integer] Seat of the player receiving the message
15
15
  :seat,
@@ -40,14 +40,16 @@ class ActionMessages
40
40
  end
41
41
  end
42
42
 
43
+ CONCATONATED_ACTIONS = PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join('')
44
+
43
45
  # @param [String] from_message FROM message (message from player)
44
46
  def self.parse_from_message(from_message)
45
47
  if from_message.strip.match(
46
- /^FROM\s*(\d+)\s*at\s*[\d\.]+\s*(#{MatchState::LABEL}\S+):([#{PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join('')}]\s*\d*)$/
48
+ /^FROM\s*(\d+)\s*at\s*[\d\.]+\s*(#{MatchState::LABEL}\S+):([#{CONCATONATED_ACTIONS}]\s*\d*)$/
47
49
  )
48
50
  FromMessage.new(
49
- $1.to_i - 1,
50
- MatchState.parse($2),
51
+ $1.to_i - 1,
52
+ MatchState.parse($2),
51
53
  PokerAction.new($3)
52
54
  )
53
55
  else
@@ -59,10 +61,10 @@ class ActionMessages
59
61
  if score_string.strip.match(
60
62
  /^SCORE:([\d\-\.|]+):([\w|]+)$/
61
63
  )
62
-
64
+
63
65
  stack_changes = $1.split '|'
64
66
  players = $2.split '|'
65
-
67
+
66
68
  players.each_index.inject({}) do |player_results, j|
67
69
  player_results[players[j].to_sym] = stack_changes[j].to_r
68
70
  player_results
@@ -73,45 +75,53 @@ class ActionMessages
73
75
  end
74
76
 
75
77
  def self.parse_to_or_from_message(message)
76
- parsed_message = ActionMessages.parse_to_message(message)
78
+ parsed_message = AcpcDealerData::ActionMessages.parse_to_message(message)
77
79
  if parsed_message.nil?
78
- ActionMessages.parse_from_message(message)
80
+ AcpcDealerData::ActionMessages.parse_from_message(message)
79
81
  else
80
82
  parsed_message
81
83
  end
82
84
  end
83
85
 
84
- class LogFile < File
85
- end
86
-
87
- def self.parse_file(acpc_log_file_path, player_names, game_def_directory, num_hands=nil)
88
- LogFile.open(acpc_log_file_path, 'r') do |file|
89
- ActionMessages.parse file, player_names, game_def_directory, num_hands
86
+ def self.parse_file(
87
+ acpc_log_file_path,
88
+ player_names,
89
+ game_def_directory,
90
+ num_hands=nil
91
+ )
92
+ AcpcDealerData::LogFile.open(acpc_log_file_path, 'r') do |file|
93
+ AcpcDealerData::ActionMessages.parse file, player_names, game_def_directory, num_hands
90
94
  end
91
95
  end
92
96
 
93
97
  alias_new :parse
94
98
 
95
- def initialize(acpc_log_statements, player_names, game_def_directory, num_hands=nil)
99
+ def initialize(
100
+ acpc_log_statements,
101
+ player_names,
102
+ game_def_directory,
103
+ num_hands=nil
104
+ )
96
105
  @final_score = nil
97
106
  @match_def = nil
98
107
  @data = acpc_log_statements.inject([]) do |accumulating_data, log_line|
99
108
  if @match_def.nil?
100
- @match_def = MatchDefinition.parse(log_line, player_names, game_def_directory)
109
+ @match_def = AcpcDealerData::MatchDefinition.parse(log_line, player_names, game_def_directory)
101
110
  else
102
- parsed_message = ActionMessages.parse_to_or_from_message(log_line)
111
+ parsed_message = AcpcDealerData::ActionMessages.parse_to_or_from_message(log_line)
103
112
  if parsed_message
104
113
  if (
105
- accumulating_data.empty? ||
114
+ accumulating_data.empty? ||
106
115
  accumulating_data.last.first[:state].hand_number != parsed_message[:state].hand_number
107
116
  )
108
117
  break accumulating_data if accumulating_data.length == num_hands
118
+
109
119
  accumulating_data << []
110
120
  end
111
121
 
112
122
  accumulating_data.last << parsed_message
113
123
  else
114
- @final_score = ActionMessages.parse_score(log_line) unless @final_score
124
+ @final_score = AcpcDealerData::ActionMessages.parse_score(log_line) unless @final_score
115
125
  end
116
126
  end
117
127
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  require 'dmorrill10-utils/class'
3
3
 
4
- require_relative 'match_definition'
4
+ require 'acpc_dealer_data/match_definition'
5
5
 
6
6
  # Monkey patch for easy boundary checking
7
7
  class Array
@@ -10,15 +10,15 @@ class Array
10
10
  end
11
11
  end
12
12
 
13
- class HandData
13
+ class AcpcDealerData::HandData
14
14
 
15
15
  exceptions :match_definitions_do_not_match, :invalid_data
16
16
 
17
- attr_reader(
17
+ attr_accessor(
18
18
  # @returns [Array<Numeric>] Chip distribution at the end of the hand
19
19
  :chip_distribution,
20
20
  # @returns [MatchDefinition] Game definition and match parameters
21
- :match_def,
21
+ :match_def,
22
22
  # @returns [Integer] Zero-index turn number within the hand
23
23
  :turn_number,
24
24
  # @returns [Turn] Turn data
@@ -37,7 +37,7 @@ class HandData
37
37
 
38
38
  def initialize(match_def, action_data, result)
39
39
  @match_def = match_def
40
-
40
+
41
41
  set_chip_distribution! result
42
42
 
43
43
  set_data! action_data
@@ -134,7 +134,7 @@ class HandData
134
134
 
135
135
  message_number += number_of_state_messages
136
136
 
137
- action_message = if action_data.in_bounds?(message_number) &&
137
+ action_message = if action_data.in_bounds?(message_number) &&
138
138
  action_data[message_number].respond_to?(:action)
139
139
 
140
140
  message_number += 1
@@ -160,7 +160,7 @@ class HandData
160
160
 
161
161
  def assert_messages_have_no_actions(state_messages)
162
162
  if state_messages.any? { |message| message.respond_to?(:action) }
163
- raise InvalidData, state_messages.find do |message|
163
+ raise InvalidData, state_messages.find do |message|
164
164
  !message.action.nil?
165
165
  end.inspect
166
166
  end
@@ -173,7 +173,7 @@ class HandData
173
173
  end
174
174
 
175
175
  def assert_message_is_from_final_turn(action_data, message_number, state_messages)
176
- if action_data.in_bounds?(message_number+1) &&
176
+ if action_data.in_bounds?(message_number+1) &&
177
177
  state_messages.last.round == action_data[message_number+1].state.round
178
178
  raise InvalidData, action_data[message_number].inspect
179
179
  end
@@ -1,20 +1,20 @@
1
1
 
2
2
  require 'dmorrill10-utils/class'
3
3
 
4
- require_relative 'match_definition'
5
-
6
- class HandResults
4
+ require 'acpc_dealer_data/match_definition'
5
+ require 'acpc_dealer_data/log_file'
7
6
 
7
+ class AcpcDealerData::HandResults
8
8
  attr_reader :data, :final_score, :match_def
9
9
 
10
10
  def self.parse_state(state_string)
11
11
  if state_string.strip.match(
12
12
  /^STATE:\d+:[cfr\d\/]+:[^:]+:([\d\-\.|]+):([\w|]+)$/
13
13
  )
14
-
14
+
15
15
  stack_changes = $1.split '|'
16
16
  players = $2.split '|'
17
-
17
+
18
18
  players.each_index.inject({}) do |player_results, j|
19
19
  player_results[players[j].to_sym] = stack_changes[j].to_r
20
20
  player_results
@@ -28,10 +28,10 @@ class HandResults
28
28
  if score_string.strip.match(
29
29
  /^SCORE:([\d\-\.|]+):([\w|]+)$/
30
30
  )
31
-
31
+
32
32
  stack_changes = $1.split '|'
33
33
  players = $2.split '|'
34
-
34
+
35
35
  players.each_index.inject({}) do |player_results, j|
36
36
  player_results[players[j].to_sym] = stack_changes[j].to_r
37
37
  player_results
@@ -41,12 +41,14 @@ class HandResults
41
41
  end
42
42
  end
43
43
 
44
- class LogFile < File
45
- end
46
-
47
- def self.parse_file(acpc_log_file_path, player_names, game_def_directory, num_hands=nil)
48
- LogFile.open(acpc_log_file_path, 'r') do |file|
49
- HandResults.parse file, player_names, game_def_directory, num_hands
44
+ def self.parse_file(
45
+ acpc_log_file_path,
46
+ player_names,
47
+ game_def_directory,
48
+ num_hands=nil
49
+ )
50
+ AcpcDealerData::LogFile.open(acpc_log_file_path, 'r') do |file|
51
+ AcpcDealerData::HandResults.parse file, player_names, game_def_directory, num_hands
50
52
  end
51
53
  end
52
54
 
@@ -55,20 +57,20 @@ class HandResults
55
57
  def initialize(acpc_log_statements, player_names, game_def_directory, num_hands=nil)
56
58
  @final_score = nil
57
59
  @match_def = nil
58
-
60
+
59
61
  @data = acpc_log_statements.inject([]) do |accumulating_data, log_line|
60
62
  if @match_def.nil?
61
- @match_def = MatchDefinition.parse(log_line, player_names, game_def_directory)
63
+ @match_def = AcpcDealerData::MatchDefinition.parse(log_line, player_names, game_def_directory)
62
64
  else
63
- parsed_message = HandResults.parse_state(log_line)
65
+ parsed_message = AcpcDealerData::HandResults.parse_state(log_line)
64
66
  if parsed_message
65
67
  accumulating_data << parsed_message
66
68
  break accumulating_data if accumulating_data.length == num_hands
67
69
  else
68
- @final_score = HandResults.parse_score(log_line) unless @final_score
70
+ @final_score = AcpcDealerData::HandResults.parse_score(log_line) unless @final_score
69
71
  end
70
72
  end
71
-
73
+
72
74
  accumulating_data
73
75
  end
74
76
  end
@@ -0,0 +1,3 @@
1
+ # Wrapper class to enable mocking log files in tests
2
+ class AcpcDealerData::LogFile < File
3
+ end
@@ -5,7 +5,7 @@ require 'acpc_poker_types/game_definition'
5
5
 
6
6
  require 'dmorrill10-utils/class'
7
7
 
8
- class MatchDefinition
8
+ class AcpcDealerData::MatchDefinition
9
9
 
10
10
  exceptions :unable_to_parse, :incorrect_number_of_player_names
11
11
 
@@ -14,19 +14,15 @@ class MatchDefinition
14
14
  def self.parse(acpc_log_string, player_names, game_def_directory)
15
15
  if acpc_log_string.strip.match(
16
16
  '^\s*#\s*name/game/hands/seed\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s*$'
17
- )
17
+ )
18
18
  name = $1
19
- game_def = GameDefinition.parse_file(File.join(game_def_directory, File.basename($2)))
19
+ game_def = GameDefinition.parse_file(
20
+ File.join(game_def_directory, File.basename($2))
21
+ )
20
22
  number_of_hands = $3
21
23
  random_seed = $4
22
24
 
23
- MatchDefinition.new(
24
- name,
25
- game_def,
26
- number_of_hands,
27
- random_seed,
28
- player_names
29
- )
25
+ new(name, game_def, number_of_hands, random_seed, player_names)
30
26
  else
31
27
  nil
32
28
  end
@@ -1,67 +1,77 @@
1
1
 
2
2
  require 'acpc_poker_types/player'
3
3
 
4
- require 'celluloid'
4
+ require 'celluloid/autostart'
5
5
 
6
6
  require 'dmorrill10-utils/class'
7
7
 
8
- require_relative 'action_messages'
9
- require_relative 'hand_data'
10
- require_relative 'hand_results'
11
- require_relative 'match_definition'
8
+ require 'acpc_dealer_data/action_messages'
9
+ require 'acpc_dealer_data/hand_data'
10
+ require 'acpc_dealer_data/hand_results'
11
+ require 'acpc_dealer_data/match_definition'
12
12
 
13
- class PokerMatchData
13
+ class AcpcDealerData::PokerMatchData
14
14
 
15
15
  exceptions :match_definitions_do_not_match, :final_scores_do_not_match, :player_data_inconsistent
16
16
 
17
- attr_reader(
17
+ attr_accessor(
18
18
  # @returns [Array<Numeric>] Chip distribution at the end of the match
19
19
  :chip_distribution,
20
20
  # @returns [MatchDefinition] Game definition and match parameters
21
21
  :match_def,
22
22
  # @returns [Integer] Zero-index turn number within the hand
23
23
  :hand_number,
24
- # @returns [HandData] Data from each hand
24
+ # @returns [AcpcDealerData::HandData] Data from each hand
25
25
  :data,
26
26
  # @returns [Array<Player>] Player information
27
- :players
28
- )
29
- attr_accessor(
27
+ :players,
30
28
  # @returns [Integer] Seat of the active player
31
29
  :seat
32
30
  )
33
31
 
34
- # @returns [PokerMatchData]
35
- def self.parse_files(action_messages_file, result_messages_file, player_names, dealer_directory, num_hands=nil)
32
+ # @returns [AcpcDealerData::PokerMatchData]
33
+ def self.parse_files(
34
+ action_messages_file,
35
+ result_messages_file,
36
+ player_names,
37
+ dealer_directory,
38
+ num_hands=nil
39
+ )
36
40
  parsed_action_messages = Celluloid::Future.new do
37
- ActionMessages.parse_file(
38
- action_messages_file,
39
- player_names,
41
+ AcpcDealerData::ActionMessages.parse_file(
42
+ action_messages_file,
43
+ player_names,
40
44
  dealer_directory,
41
45
  num_hands
42
46
  )
43
47
  end
44
- parsed_hand_results = Celluloid::Future.new do
45
- HandResults.parse_file(
46
- result_messages_file,
47
- player_names,
48
+ parsed_hand_results = Celluloid::Future.new do
49
+ AcpcDealerData::HandResults.parse_file(
50
+ result_messages_file,
51
+ player_names,
48
52
  dealer_directory,
49
53
  num_hands
50
54
  )
51
55
  end
52
56
 
53
- PokerMatchData.new(
54
- parsed_action_messages.value,
55
- parsed_hand_results.value,
56
- player_names,
57
+ new(
58
+ parsed_action_messages.value,
59
+ parsed_hand_results.value,
60
+ player_names,
57
61
  dealer_directory
58
62
  )
59
63
  end
60
64
 
61
- # @returns [PokerMatchData]
62
- def self.parse(action_messages, result_messages, player_names, dealer_directory, num_hands=nil)
65
+ # @returns [AcpcDealerData::PokerMatchData]
66
+ def self.parse(
67
+ action_messages,
68
+ result_messages,
69
+ player_names,
70
+ dealer_directory,
71
+ num_hands=nil
72
+ )
63
73
  parsed_action_messages = Celluloid::Future.new do
64
- ActionMessages.parse(
74
+ AcpcDealerData::ActionMessages.parse(
65
75
  action_messages,
66
76
  player_names,
67
77
  dealer_directory,
@@ -69,7 +79,7 @@ class PokerMatchData
69
79
  )
70
80
  end
71
81
  parsed_hand_results = Celluloid::Future.new do
72
- HandResults.parse(
82
+ AcpcDealerData::HandResults.parse(
73
83
  result_messages,
74
84
  player_names,
75
85
  dealer_directory,
@@ -77,7 +87,7 @@ class PokerMatchData
77
87
  )
78
88
  end
79
89
 
80
- PokerMatchData.new(
90
+ new(
81
91
  parsed_action_messages.value,
82
92
  parsed_hand_results.value,
83
93
  player_names,
@@ -85,7 +95,12 @@ class PokerMatchData
85
95
  )
86
96
  end
87
97
 
88
- def initialize(parsed_action_messages, parsed_hand_results, player_names, dealer_directory)
98
+ def initialize(
99
+ parsed_action_messages,
100
+ parsed_hand_results,
101
+ player_names,
102
+ dealer_directory
103
+ )
89
104
  if (
90
105
  parsed_action_messages.match_def.nil? ||
91
106
  parsed_hand_results.match_def.nil? ||
@@ -127,7 +142,7 @@ class PokerMatchData
127
142
  end
128
143
 
129
144
  def player(seat=@seat) @players[seat] end
130
-
145
+
131
146
  def for_every_hand!
132
147
  initialize_players!
133
148
 
@@ -166,7 +181,7 @@ class PokerMatchData
166
181
 
167
182
  if (
168
183
  player.active? &&
169
- !match_state.first_state_of_first_round? &&
184
+ !match_state.first_state_of_first_round? &&
170
185
  match_state.round > last_match_state.round
171
186
  )
172
187
  player.start_new_round!
@@ -185,27 +200,28 @@ class PokerMatchData
185
200
  self
186
201
  end
187
202
 
203
+ def match_has_another_round?(current_round, turn_index, turns_taken)
204
+ new_round?(current_round, turn_index) ||
205
+ players_all_in?(current_round, turn_index, turns_taken)
206
+ end
207
+
208
+ def hand_started?
209
+ @hand_number &&
210
+ current_hand.turn_number &&
211
+ current_hand.turn_number > 0
212
+ end
213
+
188
214
  def player_acting_sequence
189
215
  sequence = [[]]
190
-
191
- if (
192
- @hand_number.nil? ||
193
- current_hand.turn_number.nil? ||
194
- current_hand.turn_number < 1
195
- )
196
- return sequence
197
- end
198
-
216
+
217
+ return sequence unless hand_started?
218
+
199
219
  turns_taken = current_hand.data[0..current_hand.turn_number-1]
200
220
  turns_taken.each_with_index do |turn, turn_index|
201
221
  next unless turn.action_message
202
222
 
203
223
  sequence[turn.action_message.state.round] << turn.action_message.seat
204
-
205
- if (
206
- new_round?(sequence.length - 1 , turn_index) ||
207
- players_all_in?(sequence.length - 1, turn_index, turns_taken)
208
- )
224
+ if match_has_another_round?(sequence.length - 1, turn_index, turns_taken)
209
225
  sequence << []
210
226
  end
211
227
  end
@@ -247,7 +263,7 @@ class PokerMatchData
247
263
  end
248
264
  def opponents_cards_visible?
249
265
  return false unless current_hand
250
-
266
+
251
267
  current_hand.current_match_state.list_of_hole_card_hands.reject_empty_elements.length > 1
252
268
  end
253
269
  def player_with_dealer_button
@@ -278,15 +294,15 @@ class PokerMatchData
278
294
  end
279
295
  def betting_sequence
280
296
  sequence = [[]]
281
-
297
+
282
298
  if (
283
- @hand_number.nil? ||
284
- current_hand.turn_number.nil? ||
299
+ @hand_number.nil? ||
300
+ current_hand.turn_number.nil? ||
285
301
  current_hand.turn_number < 1
286
302
  )
287
303
  return sequence
288
304
  end
289
-
305
+
290
306
  turns_taken = current_hand.data[0..current_hand.turn_number-1]
291
307
  turns_taken.each_with_index do |turn, turn_index|
292
308
  next unless turn.action_message
@@ -315,13 +331,13 @@ class PokerMatchData
315
331
  # @match_def.game_def.min_wagers[current_hand.next_state.round]
316
332
  # ChipStack.new [@min_wager.to_i, action_with_context.amount_to_put_in_pot.to_i].max
317
333
  # end
318
-
334
+
319
335
  protected
320
336
 
321
337
  def initialize_players!
322
338
  @players = @match_def.player_names.length.times.map do |seat|
323
339
  Player.join_match(
324
- @match_def.player_names[seat],
340
+ @match_def.player_names[seat],
325
341
  seat,
326
342
  @match_def.game_def.chip_stacks[seat]
327
343
  )
@@ -346,7 +362,7 @@ class PokerMatchData
346
362
  def set_data!(parsed_action_messages, parsed_hand_results)
347
363
  @data = []
348
364
  parsed_action_messages.data.zip(parsed_hand_results.data).each do |action_messages_by_hand, hand_result|
349
- @data << HandData.new(
365
+ @data << AcpcDealerData::HandData.new(
350
366
  @match_def,
351
367
  action_messages_by_hand,
352
368
  hand_result
@@ -361,8 +377,9 @@ class PokerMatchData
361
377
  def players_all_in?(current_round, turn_index, turns_taken)
362
378
  current_hand.data.length == turn_index + 2 &&
363
379
  current_round < (@match_def.game_def.number_of_rounds - 1) &&
364
- (turns_taken[0..turn_index].count do |t|
365
- t.action_message.action.to_sym == :fold
380
+ (turns_taken[0..turn_index].count do |t|
381
+ # @todo Use FOLD constant instead once poker action has one
382
+ t.action_message.action.to_acpc_character == 'f'
366
383
  end) != @players.length - 1
367
384
  end
368
385