wizardwerdna-pokerstats 1.0.14 → 1.0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,99 +1,100 @@
1
1
  require 'iconv'
2
2
  require File.expand_path(File.dirname(__FILE__) + '/hand_history')
3
+ module Pokerstats
4
+ class PokerstarsFile
5
+ include Enumerable
3
6
 
4
- class PokerstarsFile
5
- include Enumerable
7
+ POKERSTARS_HEADER_PATTERN = /PokerStars Game #([0-9]+)/
6
8
 
7
- POKERSTARS_HEADER_PATTERN = /PokerStars Game #([0-9]+)/
8
-
9
- def self.open(filename, starting_at = 0, &block)
10
- new(filename, starting_at).open(starting_at, &block)
11
- end
9
+ def self.open(filename, starting_at = 0, &block)
10
+ new(filename, starting_at).open(starting_at, &block)
11
+ end
12
12
 
13
- def initialize(filename, starting_at = 0, transliterate_from = "ISO-8859-1", transliterate_to = "ASCII//TRANSLIT//IGNORE")
14
- @filename = File.expand_path(filename)
15
- @lastline = nil
16
- @lines = []
17
- @transliterator = Iconv.new(transliterate_to, transliterate_from)
18
- end
13
+ def initialize(filename, starting_at = 0, transliterate_from = "ISO-8859-1", transliterate_to = "ASCII//TRANSLIT//IGNORE")
14
+ @filename = File.expand_path(filename)
15
+ @lastline = nil
16
+ @lines = []
17
+ @transliterator = Iconv.new(transliterate_to, transliterate_from)
18
+ end
19
19
 
20
- def open_file_and_verify_first_line(starting_at = 0)
21
- @file = File.open(@filename, "r")
22
- self.pos=starting_at
23
- end
20
+ def open_file_and_verify_first_line(starting_at = 0)
21
+ @file = File.open(@filename, "r")
22
+ self.pos=starting_at
23
+ end
24
24
 
25
- def open(starting_at = 0)
26
- open_file_and_verify_first_line(starting_at)
27
- if block_given?
28
- begin
29
- yield self
30
- ensure
31
- close
25
+ def open(starting_at = 0)
26
+ open_file_and_verify_first_line(starting_at)
27
+ if block_given?
28
+ begin
29
+ yield self
30
+ ensure
31
+ close
32
+ end
32
33
  end
34
+ self
33
35
  end
34
- self
35
- end
36
-
37
- def closed?
38
- @file.closed?
39
- end
40
36
 
41
- def pos
42
- return @file.pos if @lastline.nil?
43
- @file.pos - @lastline.size - 1
44
- end
37
+ def closed?
38
+ @file.closed?
39
+ end
45
40
 
46
- def pos=(index)
47
- @file.pos=index unless pos == index
48
- @lastline = read_and_chomp_next_line_from_file
49
- unless @lastline && @lastline =~ POKERSTARS_HEADER_PATTERN
50
- close
51
- raise "hand record must begin with a valid header line"
41
+ def pos
42
+ return @file.pos if @lastline.nil?
43
+ @file.pos - @lastline.size - 1
52
44
  end
53
- @lines = [@lastline]
54
- end
55
45
 
56
- def eof?
57
- @lastline.nil?
58
- end
46
+ def pos=(index)
47
+ @file.pos=index unless pos == index
48
+ @lastline = read_and_chomp_next_line_from_file
49
+ unless @lastline && @lastline =~ POKERSTARS_HEADER_PATTERN
50
+ close
51
+ raise "hand record must begin with a valid header line"
52
+ end
53
+ @lines = [@lastline]
54
+ end
59
55
 
60
- def first(starting_at = 0)
61
- open(starting_at) do
62
- return next_handrecord
56
+ def eof?
57
+ @lastline.nil?
63
58
  end
64
- end
65
59
 
66
- def each
67
- yield next_handrecord
68
- yield next_handrecord until @lastline.nil?
69
- end
60
+ def first(starting_at = 0)
61
+ open(starting_at) do
62
+ return next_handrecord
63
+ end
64
+ end
70
65
 
71
- def next_handrecord
72
- starting_at = pos
73
- until @file.eof?
74
- @lastline = read_and_chomp_next_line_from_file
75
- break if @lastline =~ POKERSTARS_HEADER_PATTERN
76
- @lines << @lastline unless @lastline.empty?
66
+ def each
67
+ yield next_handrecord
68
+ yield next_handrecord until @lastline.nil?
77
69
  end
78
- result, @lines = HandHistory.new(@lines, @filename, starting_at), [@lastline]
79
- if @file.eof?
80
- @lastline = nil
81
- @index_of_last_header = nil
82
- @lines = []
83
- else
84
- @index_of_last_header = @file.pos-@lastline.size-1
85
- @lines = [@lastline]
70
+
71
+ def next_handrecord
72
+ starting_at = pos
73
+ until @file.eof?
74
+ @lastline = read_and_chomp_next_line_from_file
75
+ break if @lastline =~ POKERSTARS_HEADER_PATTERN
76
+ @lines << @lastline unless @lastline.empty?
77
+ end
78
+ result, @lines = HandHistory.new(@lines, @filename, starting_at), [@lastline]
79
+ if @file.eof?
80
+ @lastline = nil
81
+ @index_of_last_header = nil
82
+ @lines = []
83
+ else
84
+ @index_of_last_header = @file.pos-@lastline.size-1
85
+ @lines = [@lastline]
86
+ end
87
+ result
86
88
  end
87
- result
88
- end
89
89
 
90
- def close
91
- @file.close unless @file.closed?
92
- end
90
+ def close
91
+ @file.close unless @file.closed?
92
+ end
93
93
 
94
- private
94
+ private
95
95
 
96
- def read_and_chomp_next_line_from_file
97
- @transliterator.iconv(@file.readline.chomp!)
98
- end
96
+ def read_and_chomp_next_line_from_file
97
+ @transliterator.iconv(@file.readline.chomp!)
98
+ end
99
+ end
99
100
  end
@@ -1,111 +1,113 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/hand_constants')
2
2
  require File.expand_path(File.dirname(__FILE__) + '/hand_statistics')
3
3
 
4
- CASH = "[0-9$,.]+"
4
+ module Pokerstats
5
+ CASH = "[0-9$,.]+"
5
6
 
6
- class PokerstarsHandHistoryParser
7
- def self.parse_lines(lines, stats=nil)
8
- parser = self.new(stats)
9
- lines.each {|line| parser.parse(line)}
10
- end
7
+ class PokerstarsHandHistoryParser
8
+ def self.parse_lines(lines, stats=nil)
9
+ parser = self.new(stats)
10
+ lines.each {|line| parser.parse(line)}
11
+ end
11
12
 
12
- def initialize stats=nil
13
- @stats = stats || HandStatistics.new
14
- end
13
+ def initialize stats=nil
14
+ @stats = stats || HandStatistics.new
15
+ end
15
16
 
16
- def ignorable?(line)
17
- regular_expressions_for_ignorable_phrases = [
18
- /(.*): doesn't show hand/,
19
- /(.*) has timed out/,
20
- /(.*) has returned/,
21
- /(.*) leaves the table/,
22
- /(.*) joins the table at seat #[0-9]+/,
23
- /(.*) sits out/,
24
- /(.*) mucks hand/,
25
- /(.*) is sitting out/,
26
- /(.*) is (dis)?connected/,
27
- /(.*) said,/,
28
- /(.*) will be allowed to play after the button/,
29
- /(.*) was removed from the table for failing to post/,
30
- /(.*) re-buys and receives (.*) chips for (.*)/,
31
- /Seat [0-9]+: (.*) \(((small)|(big)) blind\) folded on the Flop/,
32
- /Seat [0-9]+: (.*) folded on the ((Flop)|(Turn)|(River))/,
33
- /Seat [0-9]+: (.*) folded before Flop \(didn't bet\)/,
34
- /Seat [0-9]+: (.*) (\((small blind)|(big blind)|(button)\) )?folded before Flop( \(didn't bet\))?/,
35
- /Seat [0-9]+: (.*) (\((small blind)|(big blind)|(button)\) )?collected (.*)/,
36
- /^\s*$/
37
- ]
38
- regular_expressions_for_ignorable_phrases.any?{|re| re =~ line }
39
- end
17
+ def ignorable?(line)
18
+ regular_expressions_for_ignorable_phrases = [
19
+ /(.*): doesn't show hand/,
20
+ /(.*) has timed out/,
21
+ /(.*) has returned/,
22
+ /(.*) leaves the table/,
23
+ /(.*) joins the table at seat #[0-9]+/,
24
+ /(.*) sits out/,
25
+ /(.*) mucks hand/,
26
+ /(.*) is sitting out/,
27
+ /(.*) is (dis)?connected/,
28
+ /(.*) said,/,
29
+ /(.*) will be allowed to play after the button/,
30
+ /(.*) was removed from the table for failing to post/,
31
+ /(.*) re-buys and receives (.*) chips for (.*)/,
32
+ /Seat [0-9]+: (.*) \(((small)|(big)) blind\) folded on the Flop/,
33
+ /Seat [0-9]+: (.*) folded on the ((Flop)|(Turn)|(River))/,
34
+ /Seat [0-9]+: (.*) folded before Flop \(didn't bet\)/,
35
+ /Seat [0-9]+: (.*) (\((small blind)|(big blind)|(button)\) )?folded before Flop( \(didn't bet\))?/,
36
+ /Seat [0-9]+: (.*) (\((small blind)|(big blind)|(button)\) )?collected (.*)/,
37
+ /^\s*$/
38
+ ]
39
+ regular_expressions_for_ignorable_phrases.any?{|re| re =~ line }
40
+ end
40
41
 
41
- def parse(line)
42
- begin
43
- case line
44
- when /PokerStars Game #([0-9]+): Tournament #([0-9]+), (\$[0-9+$]+) ([^\-]*) - Level ([IVXL]+) \((#{CASH})\/(#{CASH})\) - (.*)$/
45
- @stats.update_hand :name => "PS#{$1}", :description=> "#{$2}, #{$3} #{$4}", :tournament=> $2, :sb=> $6.to_d, :bb=> $7.to_d, :played_at=> Time.parse($8), :street => :prelude
46
- when /PokerStars Game #([0-9]+): +([^(]*) \((#{CASH})\/(#{CASH})\) - (.*)$/
47
- @stats.update_hand :name => "PS#{$1}", :description=> "#{$2} (#{$3}/#{$4})", :tournament=> nil, :sb=> cash_to_d($3), :bb=> cash_to_d($4), :played_at=> Time.parse($5), :street => :prelude
48
- when /PokerStars Game #([0-9]+): +([^(]*) \((#{CASH})\/(#{CASH}) USD\) - (.*)$/
49
- @stats.update_hand :name => "PS#{$1}", :description=> "#{$2} (#{$3}/#{$4})", :tournament=> nil, :sb=> cash_to_d($3), :bb=> cash_to_d($4), :played_at=> Time.parse($5), :street => :prelude
50
- when /\*\*\* HOLE CARDS \*\*\*/
51
- @stats.register_button(@stats.button)
52
- @stats.update_hand :street => :preflop
53
- when /\*\*\* FLOP \*\*\* \[(.*)\]/
54
- @stats.update_hand :street => :flop
55
- when /\*\*\* TURN \*\*\* \[([^\]]*)\] \[([^\]]*)\]/
56
- @stats.update_hand :street => :turn
57
- when /\*\*\* RIVER \*\*\* \[([^\]]*)\] \[([^\]]*)\]/
58
- @stats.update_hand :street => :river
59
- when /\*\*\* SHOW DOWN \*\*\*/
60
- @stats.update_hand :street => :showdown
61
- when /\*\*\* SUMMARY \*\*\*/
62
- @stats.update_hand :street => :summary
63
- when /PokerStars Game #([0-9]+):/
64
- raise "invalid hand record: #{line}"
65
- when /Dealt to ([^)]+) \[([^\]]+)\]/
66
- @stats.register_action($1, 'dealt', :result => :cards, :data => $2)
67
- when /(.*): shows \[(.*)\]/
68
- @stats.register_action($1, 'shows', :result => :cards, :data => $2)
69
- when /Board \[(.*)\]/
70
- @stats.update_hand :board => $1
71
- when /Total pot (#{CASH}) (((Main)|(Side)) pot(-[0-9]+)? (#{CASH}). )*\| Rake (#{CASH})/
72
- @stats.update_hand(:total_pot => cash_to_d($1), :rake => cash_to_d($8))
73
- when /Total pot (#{CASH}) Main pot (#{CASH}).( Side pot-[0-9]+ (#{CASH}).)* | Rake (#{CASH})/
74
- raise "popo!"
75
- when /Seat ([0-9]+): (.+) \(#{CASH} in chips\)( is sitting out)?/
76
- @stats.register_player(:seat => $1.to_i, :screen_name => $2)
77
- when /(.*): posts ((small)|(big)|(small \& big)) blind(s)? (#{CASH})/
78
- @stats.register_action($1, 'posts', :result => :post, :amount => cash_to_d($7))
79
- when /(.*): posts the ante (#{CASH})/
80
- @stats.register_action($1, 'antes', :result => :post, :amount => cash_to_d($2))
81
- when /Table '([0-9]+) ([0-9]+)' (.*) Seat #([0-9]+) is the button/
82
- @stats.register_button($4.to_i)
83
- when /Table '(.*)' (.*) Seat #([0-9]+) is the button/
84
- @stats.register_button($3.to_i)
85
- when /Uncalled bet \((.*)\) returned to (.*)/
86
- @stats.register_action($2, 'return', :result => :win, :amount => cash_to_d($1))
87
- when /(.+): ((folds)|(checks))/
88
- @stats.register_action($1, $2, :result => :neutral)
89
- when /(.+): ((calls)|(bets)) ((#{CASH})( and is all-in)?)?$/
90
- @stats.register_action($1, $2, :result => :pay, :amount => cash_to_d($6))
91
- when /(.+): raises (#{CASH}) to (#{CASH})( and is all-in)?$/
92
- @stats.register_action($1, 'raises', :result => :pay_to, :amount => cash_to_d($3))
93
- when /(.*) collected (.*) from ((side )|(main ))?pot/
94
- @stats.register_action($1, "wins", :result => :win, :amount => cash_to_d($2))
95
- when /Seat [0-9]+: (.*) (\((small blind)|(big blind)|(button)\) )?showed \[([^\]]+)\] and ((won) \(#{CASH}\)|(lost)) with (.*)/
96
- when /Seat [0-9]+: (.*) mucked \[([^\]]+)\]/
97
- else
98
- raise "invalid line for parse: #{line}" unless ignorable?(line)
42
+ def parse(line)
43
+ begin
44
+ case line
45
+ when /PokerStars Game #([0-9]+): Tournament #([0-9]+), (\$[0-9+$]+) ([^\-]*) - Level ([IVXL]+) \((#{CASH})\/(#{CASH})\) - (.*)$/
46
+ @stats.update_hand :name => "PS#{$1}", :description=> "#{$2}, #{$3} #{$4}", :tournament=> $2, :sb=> $6.to_d, :bb=> $7.to_d, :played_at=> Time.parse($8), :street => :prelude
47
+ when /PokerStars Game #([0-9]+): +([^(]*) \((#{CASH})\/(#{CASH})\) - (.*)$/
48
+ @stats.update_hand :name => "PS#{$1}", :description=> "#{$2} (#{$3}/#{$4})", :tournament=> nil, :sb=> cash_to_d($3), :bb=> cash_to_d($4), :played_at=> Time.parse($5), :street => :prelude
49
+ when /PokerStars Game #([0-9]+): +([^(]*) \((#{CASH})\/(#{CASH}) USD\) - (.*)$/
50
+ @stats.update_hand :name => "PS#{$1}", :description=> "#{$2} (#{$3}/#{$4})", :tournament=> nil, :sb=> cash_to_d($3), :bb=> cash_to_d($4), :played_at=> Time.parse($5), :street => :prelude
51
+ when /\*\*\* HOLE CARDS \*\*\*/
52
+ @stats.register_button(@stats.button)
53
+ @stats.update_hand :street => :preflop
54
+ when /\*\*\* FLOP \*\*\* \[(.*)\]/
55
+ @stats.update_hand :street => :flop
56
+ when /\*\*\* TURN \*\*\* \[([^\]]*)\] \[([^\]]*)\]/
57
+ @stats.update_hand :street => :turn
58
+ when /\*\*\* RIVER \*\*\* \[([^\]]*)\] \[([^\]]*)\]/
59
+ @stats.update_hand :street => :river
60
+ when /\*\*\* SHOW DOWN \*\*\*/
61
+ @stats.update_hand :street => :showdown
62
+ when /\*\*\* SUMMARY \*\*\*/
63
+ @stats.update_hand :street => :summary
64
+ when /PokerStars Game #([0-9]+):/
65
+ raise "invalid hand record: #{line}"
66
+ when /Dealt to ([^)]+) \[([^\]]+)\]/
67
+ @stats.register_action($1, 'dealt', :result => :cards, :data => $2)
68
+ when /(.*): shows \[(.*)\]/
69
+ @stats.register_action($1, 'shows', :result => :cards, :data => $2)
70
+ when /Board \[(.*)\]/
71
+ @stats.update_hand :board => $1
72
+ when /Total pot (#{CASH}) (((Main)|(Side)) pot(-[0-9]+)? (#{CASH}). )*\| Rake (#{CASH})/
73
+ @stats.update_hand(:total_pot => cash_to_d($1), :rake => cash_to_d($8))
74
+ when /Total pot (#{CASH}) Main pot (#{CASH}).( Side pot-[0-9]+ (#{CASH}).)* | Rake (#{CASH})/
75
+ raise "popo!"
76
+ when /Seat ([0-9]+): (.+) \(#{CASH} in chips\)( is sitting out)?/
77
+ @stats.register_player(:seat => $1.to_i, :screen_name => $2)
78
+ when /(.*): posts ((small)|(big)|(small \& big)) blind(s)? (#{CASH})/
79
+ @stats.register_action($1, 'posts', :result => :post, :amount => cash_to_d($7))
80
+ when /(.*): posts the ante (#{CASH})/
81
+ @stats.register_action($1, 'antes', :result => :post, :amount => cash_to_d($2))
82
+ when /Table '([0-9]+) ([0-9]+)' (.*) Seat #([0-9]+) is the button/
83
+ @stats.register_button($4.to_i)
84
+ when /Table '(.*)' (.*) Seat #([0-9]+) is the button/
85
+ @stats.register_button($3.to_i)
86
+ when /Uncalled bet \((.*)\) returned to (.*)/
87
+ @stats.register_action($2, 'return', :result => :win, :amount => cash_to_d($1))
88
+ when /(.+): ((folds)|(checks))/
89
+ @stats.register_action($1, $2, :result => :neutral)
90
+ when /(.+): ((calls)|(bets)) ((#{CASH})( and is all-in)?)?$/
91
+ @stats.register_action($1, $2, :result => :pay, :amount => cash_to_d($6))
92
+ when /(.+): raises (#{CASH}) to (#{CASH})( and is all-in)?$/
93
+ @stats.register_action($1, 'raises', :result => :pay_to, :amount => cash_to_d($3))
94
+ when /(.*) collected (.*) from ((side )|(main ))?pot/
95
+ @stats.register_action($1, "wins", :result => :win, :amount => cash_to_d($2))
96
+ when /Seat [0-9]+: (.*) (\((small blind)|(big blind)|(button)\) )?showed \[([^\]]+)\] and ((won) \(#{CASH}\)|(lost)) with (.*)/
97
+ when /Seat [0-9]+: (.*) mucked \[([^\]]+)\]/
98
+ else
99
+ raise "invalid line for parse: #{line}" unless ignorable?(line)
100
+ end
101
+ rescue => e
102
+ raise e
99
103
  end
100
- rescue => e
101
- raise e
102
104
  end
103
- end
104
105
 
105
- private
106
+ private
106
107
 
107
- def cash_to_d(string)
108
- string.gsub!(/[$, ]/,"")
109
- string.to_d
108
+ def cash_to_d(string)
109
+ string.gsub!(/[$, ]/,"")
110
+ string.to_d
111
+ end
110
112
  end
111
113
  end
data/pokerstats.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{pokerstats}
8
- s.version = "1.0.14"
8
+ s.version = "1.0.15"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew C. Greenberg"]
12
- s.date = %q{2009-08-29}
12
+ s.date = %q{2009-09-01}
13
13
  s.default_executable = %q{checkps}
14
14
  s.description = %q{a library for extracting, computing and reporting statistics of poker hands parsed from hand history files}
15
15
  s.email = %q{wizardwerdna@gmail.com}
@@ -53,8 +53,7 @@ Gem::Specification.new do |s|
53
53
  "spec/player_statistics_spec.rb",
54
54
  "spec/pokerstars_file_spec.rb",
55
55
  "spec/pokerstars_hand_history_parser.rb",
56
- "spec/spec_helper.rb",
57
- "spec/zpokerstars_hand_history_parser_integration.txt"
56
+ "spec/spec_helper.rb"
58
57
  ]
59
58
  s.homepage = %q{http://github.com/wizardwerdna/pokerstats}
60
59
  s.rdoc_options = ["--charset=UTF-8"]
@@ -2,6 +2,8 @@ require 'rubygems'
2
2
  require 'activesupport'
3
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_statistics')
5
+
6
+ include Pokerstats
5
7
  require File.expand_path(File.dirname(__FILE__) + '/hand_statistics_spec_helper')
6
8
 
7
9
  describe HandStatistics, "when created" do
@@ -3,6 +3,7 @@ require 'activesupport'
3
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_statistics')
5
5
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/player_statistics')
6
+ include Pokerstats
6
7
 
7
8
  TEST = [
8
9
  {"andy" => {
@@ -3,7 +3,7 @@ require 'activesupport'
3
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_history')
5
5
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/pokerstars_file')
6
-
6
+ include Pokerstats
7
7
 
8
8
  describe PokerstarsFile, "when opened on an empty file" do
9
9
  it "should complain" do
@@ -7,6 +7,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_histo
7
7
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_statistics')
8
8
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/pokerstars_file')
9
9
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/pokerstars_hand_history_parser')
10
+ include Pokerstats
10
11
 
11
12
  include HandConstants
12
13
 
@@ -27,7 +28,6 @@ describe PokerstarsHandHistoryParser, "when parsing structural matter" do
27
28
  :street => :prelude
28
29
  )
29
30
  @parser.parse("PokerStars Game #21650436825: Tournament #117620218, $10+$1 Hold'em No Limit - Level I (10/20) - 2008/10/31 17:25:42 ET")
30
- puts 'foo'
31
31
  puts @stats.report_hand_information
32
32
  end
33
33