Class: Pokerstats::HandStatistics

Inherits:
Object
  • Object
show all
Includes:
Pluggable, HandConstants
Defined in:
lib/pokerstats/hand_statistics.rb

Constant Summary

Constants included from HandConstants

Pokerstats::HandConstants::HAND_INFORMATION_KEYS, Pokerstats::HandConstants::HAND_RECORD_INCOMPLETE_MESSAGE, Pokerstats::HandConstants::HAND_REPORT_SPECIFICATION, Pokerstats::HandConstants::MAX_SEATS, Pokerstats::HandConstants::PLAYER_RECORDS_DUPLICATE_PLAYER_NAME, Pokerstats::HandConstants::PLAYER_RECORDS_NO_BUTTON_REGISTERED, Pokerstats::HandConstants::PLAYER_RECORDS_NO_PLAYER_REGISTERED, Pokerstats::HandConstants::PLAYER_RECORDS_OUT_OF_BALANCE, Pokerstats::HandConstants::PLAYER_RECORDS_UNREGISTERED_PLAYER

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHandStatistics

Returns a new instance of HandStatistics.



13
14
15
16
17
18
19
20
21
# File 'lib/pokerstats/hand_statistics.rb', line 13

def initialize
  install_plugins self
  @hand_information = {}
  @player_hashes = []
  @button_player_index = nil
  @cached_player_position = nil
  @street_state = nil
  street_transition(:prelude)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object (private)



216
217
218
# File 'lib/pokerstats/hand_statistics.rb', line 216

def method_missing symbol, *args
  plugins.send symbol, *args
end

Class Method Details

.hand_statistics_migration_dataObject



200
201
202
203
204
# File 'lib/pokerstats/hand_statistics.rb', line 200

def self.hand_statistics_migration_data
  HAND_REPORT_SPECIFICATION.inject("") do |string, each|
    string + "t.#{each[1]}\t#{each[0].inspect}\n"
  end
end

.player_statistics_migration_dataObject



206
207
208
209
210
211
212
213
214
# File 'lib/pokerstats/hand_statistics.rb', line 206

def self.player_statistics_migration_data
  plugin_factory.inject("") do |str, each_plugin|
    tstr = "# from #{each_plugin.inspect}\n"
    each_plugin.report_specification.each do |each_datum|
      tstr += "t.#{each_datum[1]}\t#{each_datum[0].inspect}\n"
    end
    str = str + tstr
  end
end

Instance Method Details

#aggression(description) ⇒ Object

Action Information



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/pokerstats/hand_statistics.rb', line 154

def aggression(description)
  case description
  when /call/
    :passive
  when /raise/
    :aggressive
  when /bet/
    :aggressive
  when /fold/
    :fold
  when /check/
    :check
  else
    :neutral
  end
end

#attacker?(screen_name) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/pokerstats/hand_statistics.rb', line 146

def attacker?(screen_name)
  (number_players > 2) && (button?(screen_name) || cutoff?(screen_name))
end

#bbpos?(screen_name) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/pokerstats/hand_statistics.rb', line 142

def bbpos?(screen_name)
  (number_players > 2) && position(screen_name) == 2
end

#blind?(screen_name) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
# File 'lib/pokerstats/hand_statistics.rb', line 134

def blind?(screen_name)
  (sbpos?(screen_name) || bbpos?(screen_name)) and !posted(screen_name).zero?
end

#buttonObject



99
100
101
# File 'lib/pokerstats/hand_statistics.rb', line 99

def button
  @button_player_index
end

#button?(screen_name) ⇒ Boolean

Returns:

  • (Boolean)


120
121
122
# File 'lib/pokerstats/hand_statistics.rb', line 120

def button?(screen_name)
  position(screen_name) && position(screen_name).zero?
end

#button_relative_seat(player_hash) ⇒ Object



103
104
105
# File 'lib/pokerstats/hand_statistics.rb', line 103

def button_relative_seat(player_hash)
  (player_hash[:seat] + MAX_SEATS - @button_player_index) % MAX_SEATS
end

#calculate_player_position(screen_name) ⇒ Object

long computation is cached, which cache is cleared every time a new player is registered



108
109
110
111
112
113
114
# File 'lib/pokerstats/hand_statistics.rb', line 108

def calculate_player_position screen_name
  @cached_player_position = {}
  @player_hashes.sort!{|a,b| button_relative_seat(a) <=> button_relative_seat(b)}
  @player_hashes = [@player_hashes.pop] + @player_hashes unless @player_hashes.first[:seat] == @button_player_index
  @player_hashes.each_with_index{|player, index| player[:position] = index, @cached_player_position[player[:screen_name]] = index}
  @cached_player_position[screen_name]
end

#cutoff?(screen_name) ⇒ Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/pokerstats/hand_statistics.rb', line 130

def cutoff?(screen_name)
  position(screen_name) == cutoff_position
end

#cutoff_positionObject

The cutoff position is defined as the player to the left of the button if there are three players, otherwise nil



125
126
127
128
# File 'lib/pokerstats/hand_statistics.rb', line 125

def cutoff_position
  # formerly: (number_players > 3) && (-1 % number_players)
  -1 % number_players if number_players > 3
end

#hand_recordObject

Hand Information



27
28
29
30
31
32
# File 'lib/pokerstats/hand_statistics.rb', line 27

def hand_record
  raise "#{HAND_RECORD_INCOMPLETE_MESSAGE}: #{(HAND_INFORMATION_KEYS - @hand_information.keys).inspect}" unless (HAND_INFORMATION_KEYS - @hand_information.keys).empty?
  HAND_INFORMATION_KEYS.inject({}) do |hash, key| 
    hash.merge!(key => @hand_information[key])
  end
end

#number_playersObject



59
60
61
# File 'lib/pokerstats/hand_statistics.rb', line 59

def number_players
  @player_hashes.size
end

#player_recordsObject



48
49
50
51
52
53
# File 'lib/pokerstats/hand_statistics.rb', line 48

def player_records
  raise PLAYER_RECORDS_NO_PLAYER_REGISTERED if players.empty?
  raise PLAYER_RECORDS_NO_BUTTON_REGISTERED if button.nil?
  raise PLAYER_RECORDS_OUT_OF_BALANCE if out_of_balance
  self.player_records_without_validation
end

#player_records_without_validationObject

Player Information



44
45
46
# File 'lib/pokerstats/hand_statistics.rb', line 44

def player_records_without_validation
  @player_hashes
end

#playersObject



55
56
57
# File 'lib/pokerstats/hand_statistics.rb', line 55

def players
  @player_hashes.sort{|a, b| a[:seat] <=> b[:seat]}.collect{|each| each[:screen_name]}
end

#position(screen_name) ⇒ Object



116
117
118
# File 'lib/pokerstats/hand_statistics.rb', line 116

def position screen_name
  (@cached_player_position && @cached_player_position[screen_name]) || calculate_player_position(screen_name)
end

#register_action(screen_name, description, options = {}) ⇒ Object



171
172
173
174
175
176
177
178
# File 'lib/pokerstats/hand_statistics.rb', line 171

def register_action(screen_name, description, options={})
  raise "#{PLAYER_RECORDS_UNREGISTERED_PLAYER}: #{screen_name.inspect}" unless players.member?(screen_name)
  plugins.each do |each|
    each.apply_action(
      {:screen_name => screen_name, :description => description, :aggression => aggression(description)}.update(options), 
      @street_state)
  end
end

#register_button(button_index) ⇒ Object

Button and Position Information



94
95
96
97
# File 'lib/pokerstats/hand_statistics.rb', line 94

def register_button button_index
  @cached_player_position = nil
  @button_player_index = button_index
end

#register_player(player) ⇒ Object



63
64
65
66
67
68
69
70
# File 'lib/pokerstats/hand_statistics.rb', line 63

def register_player player
  screen_name = player[:screen_name]
  raise "#{PLAYER_RECORDS_DUPLICATE_PLAYER_NAME}: #{screen_name.inspect}" if players.member?(screen_name)
  @cached_player_position = nil
  @player_hashes << player
  plugins.each{|each| each.register_player(screen_name, @street_state)}  #why the second parameter?
  street_transition_for_player(@street_state, screen_name)
end

#report_hand_informationObject



196
197
198
# File 'lib/pokerstats/hand_statistics.rb', line 196

def report_hand_information
  @hand_information
end

#report_player(player) ⇒ Object

Reporting Information



184
185
186
187
188
# File 'lib/pokerstats/hand_statistics.rb', line 184

def report_player(player)
  result = {}
  plugins.each {|each| result.merge!(each.report(player))}
  result
end

#reportsObject



190
191
192
193
194
# File 'lib/pokerstats/hand_statistics.rb', line 190

def reports
  result = {}
  players.each{|each| result[each] = report_player(each)}
  result
end

#sbpos?(screen_name) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/pokerstats/hand_statistics.rb', line 138

def sbpos?(screen_name)
  (number_players > 2) && position(screen_name) == 1
end

#streetObject

Street state information



76
77
78
# File 'lib/pokerstats/hand_statistics.rb', line 76

def street
  @street_state
end

#street_transition(street) ⇒ Object



80
81
82
83
84
# File 'lib/pokerstats/hand_statistics.rb', line 80

def street_transition street
  @street_state = street
  plugins.each{|each| each.street_transition(street)}
  players.each {|player| street_transition_for_player(street, player)}
end

#street_transition_for_player(street, screen_name) ⇒ Object



86
87
88
# File 'lib/pokerstats/hand_statistics.rb', line 86

def street_transition_for_player street, screen_name
  plugins.each{|each| each.street_transition_for_player(street, screen_name)}
end

#update_hand(update) ⇒ Object



34
35
36
37
38
# File 'lib/pokerstats/hand_statistics.rb', line 34

def update_hand update
  street_transition(update[:street]) unless update[:street] == @street_state
  @hand_information.update(update)
  self
end