icu_tournament 1.0.13 → 1.1.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.
- 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
|