pokerstats 2.0.1
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/bin/checkps +190 -0
- data/generators/pokerstats/USAGE +1 -0
- data/generators/pokerstats/pokerstats_generator.rb +7 -0
- data/generators/pokerstats/templates/create_pokerstats.rhtml +28 -0
- data/lib/pokerstats.rb +2 -0
- data/lib/pokerstats/.gitignore +0 -0
- data/lib/pokerstats/hand_constants.rb +27 -0
- data/lib/pokerstats/hand_history.rb +38 -0
- data/lib/pokerstats/hand_statistics.rb +225 -0
- data/lib/pokerstats/hand_statistics_api.rb +64 -0
- data/lib/pokerstats/player_statistics.rb +58 -0
- data/lib/pokerstats/plugins/aggression_statistics.rb +57 -0
- data/lib/pokerstats/plugins/blind_attack_statistics.rb +78 -0
- data/lib/pokerstats/plugins/cash_statistics.rb +95 -0
- data/lib/pokerstats/plugins/continuation_bet_statistics.rb +68 -0
- data/lib/pokerstats/plugins/preflop_raise_statistics.rb +50 -0
- data/lib/pokerstats/poker-edge.rb +57 -0
- data/lib/pokerstats/pokerstars_file.rb +100 -0
- data/lib/pokerstats/pokerstars_hand_history_parser.rb +141 -0
- data/pokerstats.gemspec +91 -0
- data/spec/file_empty.txt +0 -0
- data/spec/file_many_hands.txt +564 -0
- data/spec/file_one_hand.txt +52 -0
- data/spec/hand_statistics_spec.rb +846 -0
- data/spec/hand_statistics_spec_helper.rb +89 -0
- data/spec/player_statistics_spec.rb +230 -0
- data/spec/pokerstars_file_spec.rb +160 -0
- data/spec/pokerstars_hand_history_parser_spec.rb +197 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/zpokerstars_hand_history_parser_integration.rb.txt +67 -0
- metadata +125 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'bigdecimal/util'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_constants')
|
4
|
+
include HandConstants
|
5
|
+
|
6
|
+
module HandStatisticsFactories
|
7
|
+
def sample_hand
|
8
|
+
@@sample_hand_result ||= {
|
9
|
+
:session_filename => "a/b/c",
|
10
|
+
:starting_at => Time.now,
|
11
|
+
:name => "PS0001",
|
12
|
+
:description => "This is a description",
|
13
|
+
:sb => "1.00".to_d,
|
14
|
+
:bb => "2.00".to_d,
|
15
|
+
:board => "AS KS QS JS TS",
|
16
|
+
:total_pot => "100.00".to_d,
|
17
|
+
:rake => "4.00".to_d,
|
18
|
+
:played_at => Time.now,
|
19
|
+
:tournament => "T123"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def sample_player
|
24
|
+
@@sample_player_result ||= {
|
25
|
+
:screen_name => 'sample_player_screen_name',
|
26
|
+
:seat => 1
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def next_sample_player hash={}
|
31
|
+
@@sample_player_count ||= 0
|
32
|
+
player = sample_player.clone
|
33
|
+
player[:screen_name] = player[:screen_name] + "_" + @@sample_player_count.to_s
|
34
|
+
@@sample_player_count += 1
|
35
|
+
player.merge(hash)
|
36
|
+
end
|
37
|
+
|
38
|
+
def sample_action
|
39
|
+
@@sample_action_result ||= {
|
40
|
+
:state => :prelude,
|
41
|
+
:screen_name => sample_player[:screen_name],
|
42
|
+
:action => :pay,
|
43
|
+
:result => :pay,
|
44
|
+
:amount => 10,
|
45
|
+
:other_thing => :baz
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def register_street(street, hash={})
|
50
|
+
@stats.update_hand(hash.merge(:street => street))
|
51
|
+
end
|
52
|
+
|
53
|
+
def register_bet(player, amount, hash={})
|
54
|
+
@stats.register_action player[:screen_name], 'bets', hash.merge(:result => :pay, :amount => amount)
|
55
|
+
end
|
56
|
+
|
57
|
+
def register_post(player, amount, hash={})
|
58
|
+
@stats.register_action player[:screen_name], 'posts', hash.merge(:result => :post, :amount => amount)
|
59
|
+
end
|
60
|
+
|
61
|
+
def register_ante(player, amount, hash={})
|
62
|
+
@stats.register_action player[:screen_name], 'antes', hash.merge(:result => :post, :amount => amount)
|
63
|
+
end
|
64
|
+
|
65
|
+
def register_raise_to(player, amount, hash={})
|
66
|
+
@stats.register_action player[:screen_name], 'raises', hash.merge(:result => :pay_to, :amount => amount)
|
67
|
+
end
|
68
|
+
|
69
|
+
def register_call(player, amount, hash={})
|
70
|
+
@stats.register_action player[:screen_name], 'calls', hash.merge(:result => :pay, :amount => amount)
|
71
|
+
end
|
72
|
+
|
73
|
+
def register_check(player, hash={})
|
74
|
+
@stats.register_action player[:screen_name], 'checks', hash.merge(:result => :neutral)
|
75
|
+
end
|
76
|
+
|
77
|
+
def register_fold(player, hash={})
|
78
|
+
@stats.register_action player[:screen_name], 'folds', hash.merge(:result => :neutral)
|
79
|
+
end
|
80
|
+
|
81
|
+
def register_win(player, amount, hash={})
|
82
|
+
@stats.register_action player[:screen_name], 'wins', hash.merge(:result => :win, :amount => amount)
|
83
|
+
end
|
84
|
+
|
85
|
+
def register_cards(player, data, hash={})
|
86
|
+
@stats.register_action player[:screen_name], 'shows', hash.merge(:result => :cards, :data => data)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
include HandStatisticsFactories
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'activesupport'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_statistics')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/player_statistics')
|
6
|
+
include Pokerstats
|
7
|
+
|
8
|
+
TEST = [
|
9
|
+
{"andy" => {
|
10
|
+
:is_blind_attack_opportunity => false,
|
11
|
+
:is_blind_attack_opportunity_taken => nil,
|
12
|
+
:is_blind_defense_opportunity => false,
|
13
|
+
:is_blind_defense_opportunity_taken => nil,
|
14
|
+
:is_cbet_opportunity => true,
|
15
|
+
:is_cbet_opportunity_taken => true,
|
16
|
+
:posted => 1,
|
17
|
+
:paid => 2,
|
18
|
+
:won => 3,
|
19
|
+
:cards => nil,
|
20
|
+
:preflop_passive => 1,
|
21
|
+
:preflop_aggressive => 2,
|
22
|
+
:postflop_passive => 3,
|
23
|
+
:postflop_aggressive => 4,
|
24
|
+
:is_pfr_opportunity => true,
|
25
|
+
:is_pfr_opportunity_taken => true
|
26
|
+
},
|
27
|
+
"judi" => {
|
28
|
+
:is_blind_attack_opportunity => true,
|
29
|
+
:is_blind_attack_opportunity_taken => false,
|
30
|
+
:is_blind_defense_opportunity => true,
|
31
|
+
:is_blind_defense_opportunity_taken => true,
|
32
|
+
:is_cbet_opportunity => true,
|
33
|
+
:is_cbet_opportunity_taken => false,
|
34
|
+
:posted => 10,
|
35
|
+
:paid => 20,
|
36
|
+
:won => 30,
|
37
|
+
:cards => nil,
|
38
|
+
:preflop_passive => 10,
|
39
|
+
:preflop_aggressive => 20,
|
40
|
+
:postflop_passive => 30,
|
41
|
+
:postflop_aggressive => 40,
|
42
|
+
:is_pfr_opportunity => true,
|
43
|
+
:is_pfr_opportunity_taken => false
|
44
|
+
}
|
45
|
+
},
|
46
|
+
{"andy" => {
|
47
|
+
:is_blind_attack_opportunity => false,
|
48
|
+
:is_blind_attack_opportunity_taken => nil,
|
49
|
+
:is_blind_defense_opportunity => false,
|
50
|
+
:is_blind_defense_opportunity_taken => nil,
|
51
|
+
:is_cbet_opportunity => true,
|
52
|
+
:is_cbet_opportunity_taken => false,
|
53
|
+
:posted => 2,
|
54
|
+
:paid => 4,
|
55
|
+
:won => 6,
|
56
|
+
:cards => nil,
|
57
|
+
:preflop_passive => 2,
|
58
|
+
:preflop_aggressive => 4,
|
59
|
+
:postflop_passive => 6,
|
60
|
+
:postflop_aggressive => 8,
|
61
|
+
:is_pfr_opportunity => true,
|
62
|
+
:is_pfr_opportunity_taken => true
|
63
|
+
},
|
64
|
+
"judi" => {
|
65
|
+
:is_blind_attack_opportunity => true,
|
66
|
+
:is_blind_attack_opportunity_taken => false,
|
67
|
+
:is_blind_defense_opportunity => true,
|
68
|
+
:is_blind_defense_opportunity_taken => true,
|
69
|
+
:is_cbet_opportunity => false,
|
70
|
+
:is_cbet_opportunity_taken => nil,
|
71
|
+
:posted => 20,
|
72
|
+
:paid => 30,
|
73
|
+
:won => 40,
|
74
|
+
:cards => nil,
|
75
|
+
:preflop_passive => 20,
|
76
|
+
:preflop_aggressive => 40,
|
77
|
+
:postflop_passive => 60,
|
78
|
+
:postflop_aggressive => 80,
|
79
|
+
:is_pfr_opportunity => true,
|
80
|
+
:is_pfr_opportunity_taken => false
|
81
|
+
}
|
82
|
+
},
|
83
|
+
{"andy" => {
|
84
|
+
:is_blind_attack_opportunity => false,
|
85
|
+
:is_blind_attack_opportunity_taken => nil,
|
86
|
+
:is_blind_defense_opportunity => true,
|
87
|
+
:is_blind_defense_opportunity_taken => false,
|
88
|
+
:is_cbet_opportunity => false,
|
89
|
+
:is_cbet_opportunity_taken => nil,
|
90
|
+
:posted => 3,
|
91
|
+
:paid => 6,
|
92
|
+
:won => 9,
|
93
|
+
:cards => nil,
|
94
|
+
:preflop_passive => 3,
|
95
|
+
:preflop_aggressive => 6,
|
96
|
+
:postflop_passive => 9,
|
97
|
+
:postflop_aggressive => 12,
|
98
|
+
:is_pfr_opportunity => true,
|
99
|
+
:is_pfr_opportunity_taken => true
|
100
|
+
},
|
101
|
+
"judi" => {
|
102
|
+
:is_blind_attack_opportunity => true,
|
103
|
+
:is_blind_attack_opportunity_taken => true,
|
104
|
+
:is_blind_defense_opportunity => true,
|
105
|
+
:is_blind_defense_opportunity_taken => true,
|
106
|
+
:is_cbet_opportunity => false,
|
107
|
+
:is_cbet_opportunity_taken => nil,
|
108
|
+
:posted => 30,
|
109
|
+
:paid => 0,
|
110
|
+
:won => 0,
|
111
|
+
:cards => nil,
|
112
|
+
:preflop_passive => 30,
|
113
|
+
:preflop_aggressive => 60,
|
114
|
+
:postflop_passive => 90,
|
115
|
+
:postflop_aggressive => 120,
|
116
|
+
:is_pfr_opportunity => true,
|
117
|
+
:is_pfr_opportunity_taken => false
|
118
|
+
}
|
119
|
+
}
|
120
|
+
]
|
121
|
+
|
122
|
+
PS_RESULT = {
|
123
|
+
"andy" => {
|
124
|
+
:t_hands => 3,
|
125
|
+
:t_vpip => 3,
|
126
|
+
:t_posted => 6,
|
127
|
+
:t_paid => 12,
|
128
|
+
:t_won => 18,
|
129
|
+
:t_blind_attack_opportunity => 0,
|
130
|
+
:t_blind_attack_opportunity_taken => 0,
|
131
|
+
:t_blind_defense_opportunity => 1,
|
132
|
+
:t_blind_defense_opportunity_taken => 0,
|
133
|
+
:t_cbet_opportunity => 2,
|
134
|
+
:t_cbet_opportunity_taken => 1,
|
135
|
+
:t_preflop_passive => 6,
|
136
|
+
:t_preflop_aggressive => 12,
|
137
|
+
:t_postflop_passive => 18,
|
138
|
+
:t_postflop_aggressive => 24,
|
139
|
+
:t_pfr_opportunity => 3,
|
140
|
+
:t_pfr_opportunity_taken => 3
|
141
|
+
},
|
142
|
+
"judi" => {
|
143
|
+
:t_hands => 3,
|
144
|
+
:t_vpip => 2,
|
145
|
+
:t_posted => 60,
|
146
|
+
:t_paid => 50,
|
147
|
+
:t_won => 70,
|
148
|
+
:t_blind_attack_opportunity => 3,
|
149
|
+
:t_blind_attack_opportunity_taken => 1,
|
150
|
+
:t_blind_defense_opportunity => 3,
|
151
|
+
:t_blind_defense_opportunity_taken => 3,
|
152
|
+
:t_cbet_opportunity => 1,
|
153
|
+
:t_cbet_opportunity_taken => 0,
|
154
|
+
:t_preflop_passive => 60,
|
155
|
+
:t_preflop_aggressive => 120,
|
156
|
+
:t_postflop_passive => 180,
|
157
|
+
:t_postflop_aggressive => 240,
|
158
|
+
:t_pfr_opportunity => 3,
|
159
|
+
:t_pfr_opportunity_taken => 0
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
class AggregateTo
|
164
|
+
def initialize(player, stat, expected)
|
165
|
+
@player = player
|
166
|
+
@stat = stat
|
167
|
+
@expected = expected
|
168
|
+
end
|
169
|
+
|
170
|
+
def matches?(hash)
|
171
|
+
@actual = hash[@player][@stat]
|
172
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
173
|
+
return @actual == @expected
|
174
|
+
end
|
175
|
+
|
176
|
+
def failure_message
|
177
|
+
"expected report[#{@player.inspect}][#{@stat.inspect}] to aggregate to #{@expected.inspect}, got #{@actual.inspect}"
|
178
|
+
end
|
179
|
+
|
180
|
+
def negative_failure_message
|
181
|
+
"expected report[#{@player.inspect}][#{@stat.inspect}] not to aggregate to #{@expected.inspect}, but it did"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def should_correctly_aggregate(reports, stats = [])
|
186
|
+
reports.keys.each do |each_player|
|
187
|
+
stats.each do |each_stat|
|
188
|
+
reports.should AggregateTo.new(each_player, each_stat, PS_RESULT[each_player][each_stat])
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe PlayerStatistics, "when aggregating statistics" do
|
194
|
+
before do
|
195
|
+
@player_statistics = PlayerStatistics.new
|
196
|
+
for each_test in TEST
|
197
|
+
@hand_statistics = HandStatistics.new
|
198
|
+
@hand_statistics.should_receive(:reports).and_return(each_test)
|
199
|
+
@player_statistics.record(@hand_statistics)
|
200
|
+
end
|
201
|
+
@reports = @player_statistics.reports
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should produce a report with data for each player in the reports" do
|
205
|
+
players = {}
|
206
|
+
for each_hand in TEST
|
207
|
+
for each_player in each_hand.keys
|
208
|
+
players[each_player] = true
|
209
|
+
end
|
210
|
+
end
|
211
|
+
@reports.should have(players.size).keys
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should correctly aggregate aggression for each player" do
|
215
|
+
should_correctly_aggregate @reports, [:t_preflop_passive, :t_preflop_aggressive, :t_postflop_passive, :t_postflop_aggressive]
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'should correctly aggregate blind attack statistics' do
|
219
|
+
should_correctly_aggregate @reports, [:t_blind_attack_opportunity, :t_blind_attack_opportunity_taken, :t_blind_defense_opportunity, :t_blind_defense_opportunity_taken]
|
220
|
+
end
|
221
|
+
it 'should correctly aggregate cash statistics' do
|
222
|
+
should_correctly_aggregate @reports, [:t_hands, :t_vpip, :t_posted, :t_paid, :t_won]
|
223
|
+
end
|
224
|
+
it 'should correctly aggregate continuation bet statistics' do
|
225
|
+
should_correctly_aggregate @reports, [:t_cbet_opportunity, :t_cbet_opportunity_taken]
|
226
|
+
end
|
227
|
+
it 'should correctly aggregate preflop raise statistics' do
|
228
|
+
should_correctly_aggregate @reports, [:t_pfr_opportunity, :t_pfr_opportunity_taken]
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'activesupport'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/hand_history')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/pokerstats/pokerstars_file')
|
6
|
+
include Pokerstats
|
7
|
+
|
8
|
+
describe PokerstarsFile, "when opened on an empty file" do
|
9
|
+
it "should complain" do
|
10
|
+
lambda{@psfile = PokerstarsFile.open(File.dirname(__FILE__) + '/file_empty.txt')}.should raise_error
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe PokerstarsFile, "when opened on a single-hand file" do
|
15
|
+
ONE_HAND_NUMBER_OF_ENTRIES = 1
|
16
|
+
|
17
|
+
ONE_HAND_ENTRY_NUMBER_OF_LINES = 50
|
18
|
+
ONE_HAND_ENTRY_FIRST_LINE = "PokerStars Game #24759011305: Tournament #139359808, $10+$1 Hold'em No Limit - Level I (10/20) - 2009/02/09 14:02:39 ET"
|
19
|
+
ONE_HAND_ENTRY_LAST_LINE = "Seat 9: MartinBOF84 folded before Flop (didn't bet)"
|
20
|
+
|
21
|
+
before do
|
22
|
+
@psfile = PokerstarsFile.open(File.dirname(__FILE__) + '/file_one_hand.txt')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be open" do
|
26
|
+
@psfile.should_not be_closed
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not be eof" do
|
30
|
+
@psfile.should_not be_eof
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be at position zero" do
|
34
|
+
@psfile.pos.should be_zero
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should read all the hands in the test file" do
|
38
|
+
@psfile.should have(ONE_HAND_NUMBER_OF_ENTRIES).entries
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have an entry, answering to first, having the correct lines" do
|
42
|
+
@entry = @psfile.first
|
43
|
+
@entry.should have(ONE_HAND_ENTRY_NUMBER_OF_LINES).lines
|
44
|
+
@entry.lines[0].should == ONE_HAND_ENTRY_FIRST_LINE
|
45
|
+
@entry.lines[ONE_HAND_ENTRY_NUMBER_OF_LINES-1].should == ONE_HAND_ENTRY_LAST_LINE
|
46
|
+
@psfile.should be_closed
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have an entry, answering to entries, having the correct lines" do
|
50
|
+
@entry = @psfile.entries.first
|
51
|
+
@entry.should have(ONE_HAND_ENTRY_NUMBER_OF_LINES).lines
|
52
|
+
@entry.lines.first.should == ONE_HAND_ENTRY_FIRST_LINE
|
53
|
+
@entry.lines.last.should == ONE_HAND_ENTRY_LAST_LINE
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be at the end of file after reading the entry" do
|
57
|
+
@psfile.first
|
58
|
+
@psfile.should be_eof
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe PokerstarsFile, "when opened on a file encoded in Latin-1, should transliterate properly to ASCII" do
|
63
|
+
LATIN1_LINE_INDEX = 8
|
64
|
+
LATIN1_LINE_TRANSLITERATED = "Seat 8: Gw\"unni (3000 in chips) "
|
65
|
+
|
66
|
+
before do
|
67
|
+
@psfile = PokerstarsFile.open(File.dirname(__FILE__) + '/file_one_hand.txt')
|
68
|
+
@entry = @psfile.entries.first
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should properly transliterate the selected line" do
|
72
|
+
@entry.lines[LATIN1_LINE_INDEX].should == LATIN1_LINE_TRANSLITERATED
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe PokerstarsFile, "when opened on a multi-hand file" do
|
77
|
+
NUMBER_OF_ENTRIES = 12
|
78
|
+
|
79
|
+
FIRST_ENTRY_NUMBER_OF_LINES = 47
|
80
|
+
FIRST_ENTRY_FIRST_LINE = "PokerStars Game #21650146783: Hold'em No Limit ($0.25/$0.50) - 2008/10/31 17:14:44 ET"
|
81
|
+
FIRST_ENTRY_LAST_LINE = "Seat 9: ATTACCA folded before Flop (didn't bet)"
|
82
|
+
|
83
|
+
LAST_ENTRY_NUMBER_OF_LINES = 48
|
84
|
+
LAST_ENTRY_FIRST_LINE = "PokerStars Game #21650401569: Hold'em No Limit ($0.25/$0.50) - 2008/10/31 17:24:58 ET"
|
85
|
+
LAST_ENTRY_LAST_LINE = "Seat 9: ATTACCA folded before Flop (didn't bet)"
|
86
|
+
|
87
|
+
TABLE_OF_STARTING_INDICES = [0, 1526, 2997, 4594, 5939, 7650, 9174, 10740, 12137, 13446, 14589, 15823]
|
88
|
+
|
89
|
+
before do
|
90
|
+
@psfile = PokerstarsFile.open(File.dirname(__FILE__) + '/file_many_hands.txt')
|
91
|
+
@expanded_path = File.expand_path(File.dirname(__FILE__) + '/file_many_hands.txt')
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should be open" do
|
95
|
+
@psfile.should_not be_closed
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should not be eof" do
|
99
|
+
@psfile.should_not be_eof
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should read all the hands in the test file" do
|
103
|
+
@psfile.should have(NUMBER_OF_ENTRIES).entries
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should collect entries with all the proper information" do
|
107
|
+
list = TABLE_OF_STARTING_INDICES.clone
|
108
|
+
@psfile.entries.each do |handrecord|
|
109
|
+
handrecord.source.should == @expanded_path
|
110
|
+
handrecord.position.should == list.shift
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should be able to access records through valid positions" do
|
115
|
+
TABLE_OF_STARTING_INDICES.each do |index|
|
116
|
+
@entry = @psfile.first(index)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should complain when attempting to reach records through invalid positions" do
|
121
|
+
TABLE_OF_STARTING_INDICES.each do |index|
|
122
|
+
lambda {@psfile.pos=each+1}.should raise_error
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should have a first entry having the correct lines, addressable through #first" do
|
127
|
+
@psfile.entries #run through the file to see if it resets properly
|
128
|
+
@entry = @psfile.first(TABLE_OF_STARTING_INDICES.first)
|
129
|
+
@entry.should have(FIRST_ENTRY_NUMBER_OF_LINES).lines
|
130
|
+
@entry.lines.first.should == FIRST_ENTRY_FIRST_LINE
|
131
|
+
@entry.lines.last.should == FIRST_ENTRY_LAST_LINE
|
132
|
+
@psfile.should be_closed
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should have a first entry having the correct lines, addresable through #entries" do
|
136
|
+
@entries = @psfile.entries.first
|
137
|
+
@entries.should have(FIRST_ENTRY_NUMBER_OF_LINES).lines
|
138
|
+
@entries.lines.first.should == FIRST_ENTRY_FIRST_LINE
|
139
|
+
@entries.lines.last.should == FIRST_ENTRY_LAST_LINE
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should have a last entry having the correct lines, addressable through #first" do
|
143
|
+
@entry = @psfile.first(TABLE_OF_STARTING_INDICES.last)
|
144
|
+
@entry.should have(LAST_ENTRY_NUMBER_OF_LINES).lines
|
145
|
+
@entry.lines.first.should == LAST_ENTRY_FIRST_LINE
|
146
|
+
@entry.lines.last.should == LAST_ENTRY_LAST_LINE
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should have a last entry having the correct lines, addressable through #entries" do
|
150
|
+
@entries = @psfile.entries.last
|
151
|
+
@entries.should have(LAST_ENTRY_NUMBER_OF_LINES).lines
|
152
|
+
@entries.lines.first.should == LAST_ENTRY_FIRST_LINE
|
153
|
+
@entries.lines.last.should == LAST_ENTRY_LAST_LINE
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should be at the end of file after reading all the entries" do
|
157
|
+
@psfile.entries
|
158
|
+
@psfile.should be_eof
|
159
|
+
end
|
160
|
+
end
|