icu_tournament 1.0.13 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/icu_tournament/tournament.rb +32 -2
- data/lib/icu_tournament/tournament_fcsv.rb +53 -24
- data/lib/icu_tournament/tournament_krause.rb +6 -1
- data/lib/icu_tournament/tournament_sp.rb +6 -1
- data/lib/icu_tournament/version.rb +1 -1
- data/spec/spec_helper.rb +5 -0
- data/spec/tournament_fcsv_spec.rb +67 -6
- data/spec/tournament_krause_spec.rb +6 -10
- data/spec/tournament_spec.rb +21 -0
- metadata +3 -3
@@ -35,7 +35,7 @@ and then:
|
|
35
35
|
|
36
36
|
or equivalntly, just:
|
37
37
|
|
38
|
-
puts
|
38
|
+
puts t.serialize('Krause')
|
39
39
|
|
40
40
|
would result in the following output:
|
41
41
|
|
@@ -72,6 +72,22 @@ Side effects of calling <em>validate!</em> or _invalid_ include:
|
|
72
72
|
* the number of rounds will be set if not set already
|
73
73
|
* the finish date will be set if not set already and if there are round dates
|
74
74
|
|
75
|
+
Optionally, additional validation checks can be performed given a tournament
|
76
|
+
parser/serializer. For example:
|
77
|
+
|
78
|
+
t.validate!(:type => ICU::Tournament.ForeignCSV.new)
|
79
|
+
|
80
|
+
Or equivalently:
|
81
|
+
|
82
|
+
t.validate!(:type => 'ForeignCSV')
|
83
|
+
|
84
|
+
Such additional validation is always performed before a tournament is serialized.
|
85
|
+
For example, the following are equivalent and will throw an exception if
|
86
|
+
the tournament is invalid according to either the general rules or the rules
|
87
|
+
specific for the type used:
|
88
|
+
|
89
|
+
t.serialize('ForeignCSV')
|
90
|
+
ICU::Tournament::ForeignCSV.new.serialize(t)
|
75
91
|
|
76
92
|
== Ranking
|
77
93
|
|
@@ -370,6 +386,7 @@ in which case any options supplied to this method will be silently ignored.
|
|
370
386
|
check_dates
|
371
387
|
check_teams
|
372
388
|
check_ranks(:allow_none => true)
|
389
|
+
check_type(options[:type]) if options[:type]
|
373
390
|
true
|
374
391
|
end
|
375
392
|
|
@@ -386,12 +403,14 @@ in which case any options supplied to this method will be silently ignored.
|
|
386
403
|
end
|
387
404
|
|
388
405
|
# Convenience method to serialise the tournament into a supported format.
|
389
|
-
# Throws
|
406
|
+
# Throws an exception unless the name of a supported format is supplied
|
407
|
+
# or if the tournament is unsuitable for serialisation in that format.
|
390
408
|
def serialize(format)
|
391
409
|
serializer = case format.to_s.downcase
|
392
410
|
when 'krause' then ICU::Tournament::Krause.new
|
393
411
|
when 'foreigncsv' then ICU::Tournament::ForeignCSV.new
|
394
412
|
when 'swissperfect' then ICU::Tournament::SwissPerfect.new
|
413
|
+
when '' then raise "no format supplied"
|
395
414
|
else raise "unsupported serialisation format: '#{format}'"
|
396
415
|
end
|
397
416
|
serializer.serialize(self)
|
@@ -486,6 +505,17 @@ in which case any options supplied to this method will be silently ignored.
|
|
486
505
|
end
|
487
506
|
end
|
488
507
|
|
508
|
+
# Validate against a specific type.
|
509
|
+
def check_type(type)
|
510
|
+
if type.respond_to?(:validate!)
|
511
|
+
type.validate!(self)
|
512
|
+
elsif type.to_s.match(/^(ForeignCSV|Krause|SwissPerfect)$/)
|
513
|
+
parser = "ICU::Tournament::#{type.to_s}".constantize.new.validate!(self)
|
514
|
+
else
|
515
|
+
raise "invalid type supplied for validation check"
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
489
519
|
# Return an array of tie break methods and an array of tie break orders (+1 for asc, -1 for desc).
|
490
520
|
# The first and most important method is always "score", the last and least important is always "name".
|
491
521
|
def tie_break_data
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ICU
|
2
2
|
class Tournament
|
3
|
-
|
3
|
+
|
4
4
|
=begin rdoc
|
5
5
|
|
6
6
|
== Foreign CSV
|
@@ -34,7 +34,7 @@ This file can be parsed as follows.
|
|
34
34
|
|
35
35
|
If the file is correctly specified, the return value from the <em>parse_file</em> method is an instance of
|
36
36
|
ICU::Tournament (rather than <em>nil</em>, which indicates an error). In this example the file is valid, so:
|
37
|
-
|
37
|
+
|
38
38
|
tournament.name # => "Isle of Man Masters, 2007"
|
39
39
|
tournament.start # => "2007-09-22"
|
40
40
|
tournament.rounds # => 9
|
@@ -44,7 +44,7 @@ The main player (the player whose results are being reported for rating) played
|
|
44
44
|
but only 8 other players (he had a bye in round 6), so the total number of players is 9.
|
45
45
|
|
46
46
|
tournament.players.size # => 9
|
47
|
-
|
47
|
+
|
48
48
|
Each player has a unique number for the tournament. The main player always occurs first in this type of file, so his number is 1.
|
49
49
|
|
50
50
|
player = tournament.player(1)
|
@@ -86,6 +86,20 @@ Or equivalently, the _serialize_ instance method of the tournament, if the appro
|
|
86
86
|
|
87
87
|
csv = tournament.serialize('ForeignCSV')
|
88
88
|
|
89
|
+
Extra condtions, over and above the normal validation rules, apply before any tournament validates or can be serialized in this format.
|
90
|
+
|
91
|
+
* the tournament must have a _site_ attribute
|
92
|
+
* there must be at least one player with an _id_ (interpreted as an ICU ID number)
|
93
|
+
* all foreign players (those without an ICU ID) must have a _fed_ attribute (federation)
|
94
|
+
* all ICU players must have a result in every round (even if it is just bye or is unrateable)
|
95
|
+
* the opponents of all ICU players must have a federation (this could include other ICU players)
|
96
|
+
|
97
|
+
If any of these are not satisfied, then the following method calls will all raise an exception:
|
98
|
+
|
99
|
+
tournament.validate!(:type => 'ForeignCSV')
|
100
|
+
tournament.serialize('ForeignCSV')
|
101
|
+
ICU::Tournament::ForeignCSV.new.serialize(tournament)
|
102
|
+
|
89
103
|
You can also build the tournament object from scratch using your own data and then serialize it.
|
90
104
|
For example, here are the commands to reproduce the example above.
|
91
105
|
|
@@ -105,30 +119,29 @@ For example, here are the commands to reproduce the example above.
|
|
105
119
|
t.add_result(ICU::Result.new(3, 1, 'D', :opponent => 4, :colour => 'B'))
|
106
120
|
t.add_result(ICU::Result.new(4, 1, 'W', :opponent => 5, :colour => 'W'))
|
107
121
|
t.add_result(ICU::Result.new(5, 1, 'W', :opponent => 6, :colour => 'B'))
|
108
|
-
t.add_result(ICU::Result.new(6, 1, 'L'))
|
122
|
+
t.add_result(ICU::Result.new(6, 1, 'L'))
|
109
123
|
t.add_result(ICU::Result.new(7, 1, 'D', :opponent => 7, :colour => 'W'))
|
110
124
|
t.add_result(ICU::Result.new(8, 1, 'L', :opponent => 8, :colour => 'B'))
|
111
125
|
t.add_result(ICU::Result.new(9, 1, 'D', :opponent => 9, :colour => 'W'))
|
112
|
-
t.validate!
|
113
126
|
puts t.serialize('ForeignCSV')
|
114
|
-
|
127
|
+
|
115
128
|
=end
|
116
129
|
|
117
130
|
class ForeignCSV
|
118
131
|
attr_reader :error
|
119
|
-
|
132
|
+
|
120
133
|
# Parse CSV data returning a Tournament on success or raising an exception on error.
|
121
134
|
def parse!(csv)
|
122
135
|
@state, @line, @round, @sum, @error = 0, 0, nil, nil, nil
|
123
136
|
@tournament = Tournament.new('Dummy', '2000-01-01')
|
124
|
-
|
137
|
+
|
125
138
|
Util::CSV.parse(csv, :row_sep => :auto) do |r|
|
126
139
|
@line += 1 # increment line number
|
127
140
|
next if r.size == 0 # skip empty lines
|
128
141
|
r = r.map{|c| c.nil? ? '' : c.strip} # trim all spaces, turn nils to blanks
|
129
142
|
next if r[0] == '' # skip blanks in column 1
|
130
143
|
@r = r # remember this record for later
|
131
|
-
|
144
|
+
|
132
145
|
begin
|
133
146
|
case @state
|
134
147
|
when 0 then event
|
@@ -145,7 +158,7 @@ For example, here are the commands to reproduce the example above.
|
|
145
158
|
raise
|
146
159
|
end
|
147
160
|
end
|
148
|
-
|
161
|
+
|
149
162
|
unless @state == 4
|
150
163
|
exp = case @state
|
151
164
|
when 0 then "the event name"
|
@@ -158,12 +171,12 @@ For example, here are the commands to reproduce the example above.
|
|
158
171
|
raise "line #{@line}: premature termination - expected #{exp}"
|
159
172
|
end
|
160
173
|
raise "line #{@line}: no players found in file" if @tournament.players.size == 0
|
161
|
-
|
174
|
+
|
162
175
|
@tournament.validate!
|
163
176
|
|
164
177
|
@tournament
|
165
178
|
end
|
166
|
-
|
179
|
+
|
167
180
|
# Parse CSV data returning a Tournament on success or a nil on failure.
|
168
181
|
# In the case of failure, an error message can be retrived via the <em>error</em> method.
|
169
182
|
def parse(csv)
|
@@ -174,13 +187,13 @@ For example, here are the commands to reproduce the example above.
|
|
174
187
|
nil
|
175
188
|
end
|
176
189
|
end
|
177
|
-
|
190
|
+
|
178
191
|
# Same as <em>parse!</em> except the input is a file name rather than file contents.
|
179
192
|
def parse_file!(file)
|
180
193
|
csv = open(file) { |f| f.read }
|
181
194
|
parse!(csv)
|
182
195
|
end
|
183
|
-
|
196
|
+
|
184
197
|
# Same as <em>parse</em> except the input is a file name rather than file contents.
|
185
198
|
def parse_file(file)
|
186
199
|
begin
|
@@ -190,10 +203,10 @@ For example, here are the commands to reproduce the example above.
|
|
190
203
|
nil
|
191
204
|
end
|
192
205
|
end
|
193
|
-
|
206
|
+
|
194
207
|
# Serialise a tournament back into CSV format.
|
195
208
|
def serialize(t)
|
196
|
-
|
209
|
+
t.validate!(:type => self)
|
197
210
|
Util::CSV.generate do |csv|
|
198
211
|
csv << ["Event", t.name]
|
199
212
|
csv << ["Start", t.start]
|
@@ -226,36 +239,52 @@ For example, here are the commands to reproduce the example above.
|
|
226
239
|
end
|
227
240
|
end
|
228
241
|
|
242
|
+
# Additional tournament validation rules for this specific type.
|
243
|
+
def validate!(t)
|
244
|
+
raise "missing site" unless t.site.to_s.length > 0
|
245
|
+
icu = t.players.find_all { |p| p.id }
|
246
|
+
raise "there must be at least one ICU player (with an ID number)" if icu.size == 0
|
247
|
+
foreign = t.players.find_all { |p| !p.id }
|
248
|
+
raise "all foreign players must have a federation" if foreign.detect { |f| !f.fed }
|
249
|
+
icu.each do |p|
|
250
|
+
(1..t.rounds).each do |r|
|
251
|
+
result = p.find_result(r)
|
252
|
+
raise "ICU players must have a result in every round" unless result
|
253
|
+
raise "all opponents of ICU players must have a federation" if result.opponent && !t.player(result.opponent).fed
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
229
258
|
private
|
230
|
-
|
259
|
+
|
231
260
|
def event
|
232
261
|
abort "the 'Event' keyword", 0 unless @r[0].match(/^(Event|Tournament)$/i)
|
233
262
|
abort "the event name", 1 unless @r.size > 1 && @r[1] != ''
|
234
263
|
@tournament.name = @r[1]
|
235
264
|
@state = 1
|
236
265
|
end
|
237
|
-
|
266
|
+
|
238
267
|
def start
|
239
268
|
abort "the 'Start' keyword", 0 unless @r[0].match(/^(Start(\s+Date)?|Date)$/i)
|
240
269
|
abort "the start date", 1 unless @r.size > 1 && @r[1] != ''
|
241
270
|
@tournament.start = @r[1]
|
242
271
|
@state = 2
|
243
272
|
end
|
244
|
-
|
273
|
+
|
245
274
|
def rounds
|
246
275
|
abort "the 'Rounds' keyword", 0 unless @r[0].match(/(Number of )?Rounds$/)
|
247
276
|
abort "the number of rounds", 1 unless @r.size > 1 && @r[1].match(/^[1-9]\d*/)
|
248
277
|
@tournament.rounds = @r[1]
|
249
278
|
@state = 3
|
250
279
|
end
|
251
|
-
|
280
|
+
|
252
281
|
def website
|
253
282
|
abort "the 'Website' keyword", 0 unless @r[0].match(/^(Web(\s?site)?|Site)$/i)
|
254
283
|
abort "the event website", 1 unless @r.size > 1 && @r[1] != ''
|
255
284
|
@tournament.site = @r[1]
|
256
285
|
@state = 4
|
257
286
|
end
|
258
|
-
|
287
|
+
|
259
288
|
def player
|
260
289
|
abort "the 'Player' keyword", 0 unless @r[0].match(/^Player$/i)
|
261
290
|
abort "a player's ICU number", 1 unless @r.size > 1 && @r[1].match(/^[1-9]/i)
|
@@ -274,7 +303,7 @@ For example, here are the commands to reproduce the example above.
|
|
274
303
|
@round = 0
|
275
304
|
@state = 5
|
276
305
|
end
|
277
|
-
|
306
|
+
|
278
307
|
def result
|
279
308
|
@round+= 1
|
280
309
|
abort "round number #{round}", 0 unless @r[0].to_i == @round
|
@@ -309,14 +338,14 @@ For example, here are the commands to reproduce the example above.
|
|
309
338
|
end
|
310
339
|
@state = 6 if @round == @tournament.rounds
|
311
340
|
end
|
312
|
-
|
341
|
+
|
313
342
|
def total
|
314
343
|
points = @player.points
|
315
344
|
abort "the 'Total' keyword", 0 unless @r[0].match(/^Total$/i)
|
316
345
|
abort "the player's (#{@player.object_id}, #{@player.results.size}) total points to be #{points}", 1 unless @r[1].to_f == points
|
317
346
|
@state = 4
|
318
347
|
end
|
319
|
-
|
348
|
+
|
320
349
|
def abort(expected, cell)
|
321
350
|
got = @r[cell]
|
322
351
|
error = "line #{@line}"
|
@@ -199,7 +199,7 @@ attributes in an ICU::Tournament instance.
|
|
199
199
|
|
200
200
|
# Serialise a tournament back into Krause format.
|
201
201
|
def serialize(t)
|
202
|
-
|
202
|
+
t.validate!(:type => self)
|
203
203
|
krause = ''
|
204
204
|
krause << "012 #{t.name}\n"
|
205
205
|
krause << "022 #{t.city}\n" if t.city
|
@@ -225,6 +225,11 @@ attributes in an ICU::Tournament instance.
|
|
225
225
|
krause
|
226
226
|
end
|
227
227
|
|
228
|
+
# Additional tournament validation rules for this specific type.
|
229
|
+
def validate!(t)
|
230
|
+
# None.
|
231
|
+
end
|
232
|
+
|
228
233
|
private
|
229
234
|
|
230
235
|
def set_name
|
@@ -146,7 +146,7 @@ See ICU::Tournament for more about tie-breaks.
|
|
146
146
|
|
147
147
|
# Serialise a tournament to SwissPerfect text export format.
|
148
148
|
def serialize(t)
|
149
|
-
|
149
|
+
t.validate!(:type => self)
|
150
150
|
|
151
151
|
# Ensure a nice set of numbers.
|
152
152
|
t.renumber(:order)
|
@@ -173,6 +173,11 @@ See ICU::Tournament for more about tie-breaks.
|
|
173
173
|
sp
|
174
174
|
end
|
175
175
|
|
176
|
+
# Additional tournament validation rules for this specific type.
|
177
|
+
def validate!(t)
|
178
|
+
# None.
|
179
|
+
end
|
180
|
+
|
176
181
|
private
|
177
182
|
|
178
183
|
def get_files(file, arg)
|
data/spec/spec_helper.rb
CHANGED
@@ -412,10 +412,6 @@ CSV
|
|
412
412
|
it "should serialize back to the original" do
|
413
413
|
@f.serialize(@t).should == @csv
|
414
414
|
end
|
415
|
-
|
416
|
-
it "should return nil on invalid input" do
|
417
|
-
@f.serialize('Rubbish').should be_nil
|
418
|
-
end
|
419
415
|
end
|
420
416
|
|
421
417
|
context "serialisation of ForeignCSV documentation example" do
|
@@ -515,9 +511,8 @@ Player,456,Fox,Anthony
|
|
515
511
|
9,=,W,Phillips,Roy,2271,,MAU
|
516
512
|
Total,4.0
|
517
513
|
CSV
|
518
|
-
@t = ICU::Tournament.new("Isle of Man Masters, 2007", '2007-09-22'
|
514
|
+
@t = ICU::Tournament.new("Isle of Man Masters, 2007", '2007-09-22')
|
519
515
|
@t.site = 'http://www.bcmchess.co.uk/monarch2007/'
|
520
|
-
@t.rounds = 9
|
521
516
|
@t.add_player(ICU::Player.new('Anthony', 'Fox', 1, :id => 456, :rating => 2100, :fed => 'IRL'))
|
522
517
|
@t.add_player(ICU::Player.new('Peter P.', 'Taylor', 2, :rating => 2209, :fed => 'ENG'))
|
523
518
|
@t.add_player(ICU::Player.new('Egozi', 'Nadav', 3, :rating => 2205, :fed => 'ISR'))
|
@@ -574,6 +569,72 @@ CSV
|
|
574
569
|
t.players.size.should == 16
|
575
570
|
end
|
576
571
|
end
|
572
|
+
|
573
|
+
context "type validation" do
|
574
|
+
before(:each) do
|
575
|
+
@p = ICU::Tournament::ForeignCSV.new
|
576
|
+
@t = ICU::Tournament.new("Isle of Man Masters, 2007", '2007-09-22')
|
577
|
+
@t.site = 'http://www.bcmchess.co.uk/monarch2007/'
|
578
|
+
@t.add_player(ICU::Player.new('Anthony', 'Fox', 1, :id => 456))
|
579
|
+
@t.add_player(ICU::Player.new('Peter', 'Cafolla', 2, :id => 159))
|
580
|
+
@t.add_player(ICU::Player.new('Peter P.', 'Taylor', 10, :rating => 2209, :fed => 'ENG'))
|
581
|
+
@t.add_player(ICU::Player.new('Egozi', 'Nadav', 20, :rating => 2205, :fed => 'ISR'))
|
582
|
+
@t.add_player(ICU::Player.new('Tim R.', 'Spanton', 30, :rating => 1982, :fed => 'ENG'))
|
583
|
+
@t.add_player(ICU::Player.new('Alan', 'Grant', 40, :rating => 2223, :fed => 'SCO'))
|
584
|
+
@t.add_result(ICU::Result.new(1, 1, 'W', :opponent => 10, :colour => 'W'))
|
585
|
+
@t.add_result(ICU::Result.new(1, 2, 'L', :opponent => 20, :colour => 'B'))
|
586
|
+
@t.add_result(ICU::Result.new(2, 1, 'D', :opponent => 30, :colour => 'B'))
|
587
|
+
@t.add_result(ICU::Result.new(2, 2, 'L', :opponent => 40, :colour => 'W'))
|
588
|
+
end
|
589
|
+
|
590
|
+
it "should pass" do
|
591
|
+
@t.invalid.should be_false
|
592
|
+
@t.invalid(:type => @p).should be_false
|
593
|
+
end
|
594
|
+
|
595
|
+
it "should fail if there's no site" do
|
596
|
+
@t.site = nil;
|
597
|
+
@t.invalid(:type => @p).to_s.should match(/site/)
|
598
|
+
end
|
599
|
+
|
600
|
+
it "should fail if there are no ICU players" do
|
601
|
+
[1, 2].each { |n| @t.player(n).id = nil }
|
602
|
+
@t.player(2).id = nil;
|
603
|
+
@t.invalid(:type => @p).to_s.should match(/ID/)
|
604
|
+
end
|
605
|
+
|
606
|
+
it "should fail unless all foreign players have a federation" do
|
607
|
+
@t.player(10).fed = nil;
|
608
|
+
@t.invalid(:type => @p).to_s.should match(/federation/)
|
609
|
+
end
|
610
|
+
|
611
|
+
it "should fail unless every ICU player has a result in every round" do
|
612
|
+
@t.add_player(ICU::Player.new('Mark', 'Orr', 3, :id => 1350))
|
613
|
+
@t.add_result(ICU::Result.new(1, 3, 'W', :opponent => 30, :colour => 'B'))
|
614
|
+
@t.invalid(:type => @p).to_s.should match(/result/)
|
615
|
+
@t.add_result(ICU::Result.new(2, 3, 'W', :opponent => 10, :colour => 'W'))
|
616
|
+
@t.invalid(:type => @p).should be_false
|
617
|
+
end
|
618
|
+
|
619
|
+
it "should fail unless every ICU player's opponents have a federation" do
|
620
|
+
@t.add_player(ICU::Player.new('Mark', 'Orr', 3, :id => 1350))
|
621
|
+
@t.add_result(ICU::Result.new(1, 3, 'W', :opponent => 30, :colour => 'B'))
|
622
|
+
@t.add_result(ICU::Result.new(2, 3, 'W', :opponent => 10, :colour => 'W'))
|
623
|
+
@t.add_result(ICU::Result.new(3, 1, 'D', :opponent => 40, :colour => 'W'))
|
624
|
+
@t.add_result(ICU::Result.new(3, 2, 'L', :opponent => 3, :colour => 'B'))
|
625
|
+
@t.invalid(:type => @p).to_s.should match(/opponents.*federation/)
|
626
|
+
@t.player(2).fed = 'IRL'
|
627
|
+
@t.invalid(:type => @p).to_s.should match(/opponents.*federation/)
|
628
|
+
@t.player(3).fed = 'IRL'
|
629
|
+
@t.invalid(:type => @p).should be_false
|
630
|
+
end
|
631
|
+
|
632
|
+
it "should be serializable unless invalid" do
|
633
|
+
lambda { @p.serialize(@t) }.should_not raise_error
|
634
|
+
@t.site = nil;
|
635
|
+
lambda { @p.serialize(@t) }.should raise_error
|
636
|
+
end
|
637
|
+
end
|
577
638
|
end
|
578
639
|
end
|
579
640
|
end
|
@@ -158,7 +158,7 @@ KRAUSE
|
|
158
158
|
@t.add_result(ICU::Result.new(1, 1, 'L', :opponent => 2, :colour => 'B'))
|
159
159
|
@t.add_result(ICU::Result.new(2, 1, 'L', :opponent => 2, :colour => 'W', :rateable => false))
|
160
160
|
@t.add_result(ICU::Result.new(3, 1, 'W', :opponent => 2, :colour => 'B'))
|
161
|
-
@t.add_result(ICU::Result.new(4, 1, '
|
161
|
+
@t.add_result(ICU::Result.new(4, 1, 'D', :opponent => 2, :colour => 'W'))
|
162
162
|
serializer = ICU::Tournament::Krause.new
|
163
163
|
@k = serializer.serialize(@t)
|
164
164
|
end
|
@@ -173,7 +173,7 @@ KRAUSE
|
|
173
173
|
end
|
174
174
|
|
175
175
|
context "serialisation" do
|
176
|
-
before(:
|
176
|
+
before(:each) do
|
177
177
|
@krause = <<KRAUSE
|
178
178
|
012 Las Vegas National Open
|
179
179
|
022 Las Vegas
|
@@ -204,10 +204,6 @@ KRAUSE
|
|
204
204
|
it "should serialize using the convenience method of the tournament object" do
|
205
205
|
@t.serialize('Krause').should == @krause
|
206
206
|
end
|
207
|
-
|
208
|
-
it "should return nil on invalid input" do
|
209
|
-
@q.serialize('Rubbish').should be_nil
|
210
|
-
end
|
211
207
|
end
|
212
208
|
|
213
209
|
context "auto-ranking" do
|
@@ -374,13 +370,13 @@ KRAUSE
|
|
374
370
|
lambda { t = @p.parse!(@k) }.should raise_error(/opponent/)
|
375
371
|
end
|
376
372
|
end
|
377
|
-
|
373
|
+
|
378
374
|
context "parsing files" do
|
379
375
|
before(:each) do
|
380
376
|
@p = ICU::Tournament::Krause.new
|
381
377
|
@s = File.dirname(__FILE__) + '/samples/krause'
|
382
378
|
end
|
383
|
-
|
379
|
+
|
384
380
|
it "should error on a non-existant valid file" do
|
385
381
|
file = "#{@s}/not_there.tab"
|
386
382
|
lambda { @p.parse_file!(file) }.should raise_error
|
@@ -388,7 +384,7 @@ KRAUSE
|
|
388
384
|
t.should be_nil
|
389
385
|
@p.error.should match(/no such file/i)
|
390
386
|
end
|
391
|
-
|
387
|
+
|
392
388
|
it "should error on an invalid file" do
|
393
389
|
file = "#{@s}/invalid.tab"
|
394
390
|
lambda { @p.parse_file!(file) }.should raise_error
|
@@ -396,7 +392,7 @@ KRAUSE
|
|
396
392
|
t.should be_nil
|
397
393
|
@p.error.should match(/tournament name missing/i)
|
398
394
|
end
|
399
|
-
|
395
|
+
|
400
396
|
it "should parse a valid file" do
|
401
397
|
file = "#{@s}/valid.tab"
|
402
398
|
lambda { @p.parse_file!(file) }.should_not raise_error
|
data/spec/tournament_spec.rb
CHANGED
@@ -853,5 +853,26 @@ EOS
|
|
853
853
|
lambda { @c.parse_file!("#{@s}/krause/valid.tab", 'NoSuchType') }.should raise_error(/invalid format/i)
|
854
854
|
end
|
855
855
|
end
|
856
|
+
|
857
|
+
context "type specific validation" do
|
858
|
+
before(:all) do
|
859
|
+
@t = Tournament.new('Bangor Bash', '2009-11-09')
|
860
|
+
@t.add_player(Player.new('Bobby', 'Fischer', 1))
|
861
|
+
@t.add_player(Player.new('Garry', 'Kasparov', 2))
|
862
|
+
@t.add_player(Player.new('Mark', 'Orr', 3))
|
863
|
+
@t.add_result(Result.new(1, 1, '=', :opponent => 2, :colour => 'W'))
|
864
|
+
@t.add_result(Result.new(2, 2, 'L', :opponent => 3, :colour => 'W'))
|
865
|
+
@t.add_result(Result.new(3, 3, 'W', :opponent => 1, :colour => 'W'))
|
866
|
+
end
|
867
|
+
|
868
|
+
it "should pass generic validation" do
|
869
|
+
@t.invalid.should be_false
|
870
|
+
end
|
871
|
+
|
872
|
+
it "should fail type-specific validation when the type supplied is inappropriate" do
|
873
|
+
@t.invalid(:type => String).should match(/invalid type/)
|
874
|
+
@t.invalid(:type => "AbCd").should match(/invalid type/)
|
875
|
+
end
|
876
|
+
end
|
856
877
|
end
|
857
878
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 1.0.13
|
9
|
+
version: 1.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mark Orr
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-17 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|