sanichi-chess_icu 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +1 -1
- data/lib/tournament.rb +48 -27
- data/lib/tournament_krause.rb +23 -3
- data/spec/tournament_krause_spec.rb +12 -5
- data/spec/tournament_spec.rb +130 -51
- metadata +1 -1
data/VERSION.yml
CHANGED
data/lib/tournament.rb
CHANGED
@@ -35,29 +35,36 @@ raise an exception if the players it references through their tournament numbers
|
|
35
35
|
|
36
36
|
A tournament can be validated with either the _validate!_ or _invalid_ methods.
|
37
37
|
On success, the first returns true while the second returns false.
|
38
|
-
On error, the first throws an exception while the second returns a description of the
|
38
|
+
On error, the first throws an exception while the second returns a description of the error.
|
39
39
|
|
40
40
|
Validations checks that:
|
41
41
|
|
42
42
|
* there are at least two players
|
43
43
|
* every player has a least one result
|
44
|
-
* the round numbers are consistent
|
45
|
-
* the tournament dates are consistent
|
46
|
-
* the player ranks are consistent
|
44
|
+
* the round numbers of the players results are consistent
|
45
|
+
* the tournament dates (start, finish, round dates) are consistent
|
46
|
+
* the player ranks are consistent with their scores
|
47
47
|
|
48
|
-
|
48
|
+
Side effects of calling _validate!_ or _invalid_ include:
|
49
49
|
|
50
|
-
*
|
51
|
-
*
|
50
|
+
* the number of rounds will be set if not set already
|
51
|
+
* the finish date will be set if not set already and if there are round dates
|
52
52
|
|
53
|
-
|
53
|
+
If the _rerank_ option is set, as in this example:
|
54
54
|
|
55
|
-
tournament.validate!(:
|
55
|
+
tournament.validate!(:rerank => true)
|
56
|
+
|
57
|
+
then there are additional side effects of validating a tournament:
|
58
|
+
|
59
|
+
* the players will be ranked if no players have any rank
|
60
|
+
* the players will be reranked if the existing ranking is inconsistent
|
61
|
+
|
62
|
+
Ranking is consistent if either no players have any rank or if all players have a rank and no player is ranked higher than another player with more points.
|
56
63
|
|
57
64
|
=end
|
58
65
|
|
59
66
|
class Tournament
|
60
|
-
attr_reader :name, :start, :finish, :
|
67
|
+
attr_reader :name, :rounds, :start, :finish, :round_dates, :site, :city, :fed, :type, :arbiter, :deputy, :time_control
|
61
68
|
|
62
69
|
# Constructor. Name and start date must be supplied. Other attributes are optional.
|
63
70
|
def initialize(name, start, opt={})
|
@@ -65,6 +72,7 @@ For example:
|
|
65
72
|
self.start = start
|
66
73
|
[:finish, :rounds, :site, :city, :fed, :type, :arbiter, :deputy, :time_control].each { |a| self.send("#{a}=", opt[a]) unless opt[a].nil? }
|
67
74
|
@player = {}
|
75
|
+
@round_dates = []
|
68
76
|
end
|
69
77
|
|
70
78
|
# Set the tournament name.
|
@@ -120,6 +128,20 @@ For example:
|
|
120
128
|
raise "invalid number of rounds (#{rounds})" unless @rounds.nil? || @rounds > 0
|
121
129
|
end
|
122
130
|
|
131
|
+
# Add a round date.
|
132
|
+
def add_round_date(round_date)
|
133
|
+
round_date = round_date.to_s.strip
|
134
|
+
parsed_date = Util.parsedate(round_date)
|
135
|
+
raise "invalid round date (#{round_date})" unless parsed_date
|
136
|
+
@round_dates << parsed_date
|
137
|
+
@round_dates.sort!
|
138
|
+
end
|
139
|
+
|
140
|
+
# Return the date of a given round, or nil if unavailable.
|
141
|
+
def round_date(round)
|
142
|
+
@round_dates[round-1]
|
143
|
+
end
|
144
|
+
|
123
145
|
# Set the tournament web site. Should be either unknown (_nil_) or a reasonably valid looking URL.
|
124
146
|
def site=(site)
|
125
147
|
@site = site.to_s.strip
|
@@ -168,7 +190,7 @@ For example:
|
|
168
190
|
@player[num]
|
169
191
|
end
|
170
192
|
|
171
|
-
# Return an array of all players in order of their player
|
193
|
+
# Return an array of all players in order of their player number.
|
172
194
|
def players
|
173
195
|
@player.values.sort_by{ |p| p.num }
|
174
196
|
end
|
@@ -224,9 +246,9 @@ For example:
|
|
224
246
|
def validate!(options={})
|
225
247
|
begin check_ranks rescue rerank end if options[:rerank]
|
226
248
|
check_players
|
227
|
-
check_dates
|
228
249
|
check_rounds
|
229
|
-
|
250
|
+
check_dates
|
251
|
+
check_ranks(:allow_none => true)
|
230
252
|
true
|
231
253
|
end
|
232
254
|
|
@@ -238,12 +260,6 @@ For example:
|
|
238
260
|
@player.each { |num, p| raise "player #{num} has no results" if p.results.size == 0 }
|
239
261
|
end
|
240
262
|
|
241
|
-
# Check dates are consistent.
|
242
|
-
def check_dates
|
243
|
-
# If there is a start date and an end date, the start should not come after the end.
|
244
|
-
raise "start date (#{start}) is after end date (#{finish})" if start && finish && start > finish
|
245
|
-
end
|
246
|
-
|
247
263
|
# Round should go from 1 to a maximum, there should be at least one result in every round and,
|
248
264
|
# if the number of rounds has been set, it should agree with the largest round from the results.
|
249
265
|
def check_rounds
|
@@ -264,13 +280,23 @@ For example:
|
|
264
280
|
end
|
265
281
|
end
|
266
282
|
|
283
|
+
# Check dates are consistent.
|
284
|
+
def check_dates
|
285
|
+
raise "start date (#{start}) is after end date (#{finish})" if @start && @finish && @start > @finish
|
286
|
+
if @round_dates.size > 0
|
287
|
+
raise "the number of round dates (#{@round_dates.size}) does not match the number of rounds (#{@rounds})" unless @round_dates.size == @rounds
|
288
|
+
raise "the date of the first round (#{@round_dates[0]}) comes before the start (#{@start}) of the tournament" if @start && @start > @round_dates[0]
|
289
|
+
raise "the date of the last round (#{@round_dates[-1]}) comes after the end (#{@finish}) of the tournament" if @finish && @finish < @round_dates[-1]
|
290
|
+
@finish = @round_dates[-1] unless @finish
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
267
294
|
# Check if the players ranking is consistent, which will be true if:
|
268
295
|
# * every player has a rank
|
269
296
|
# * no two players have the same rank
|
270
297
|
# * the highest rank is 1
|
271
298
|
# * the lowest rank is equal to the total of players
|
272
|
-
def check_ranks
|
273
|
-
# No two players can have the same rank.
|
299
|
+
def check_ranks(options)
|
274
300
|
ranks = Hash.new
|
275
301
|
@player.values.each do |p|
|
276
302
|
if p.rank
|
@@ -278,16 +304,11 @@ For example:
|
|
278
304
|
ranks[p.rank] = p
|
279
305
|
end
|
280
306
|
end
|
281
|
-
|
282
|
-
# Otherwise, every player has to have a rank.
|
307
|
+
return if ranks.size == 0 && options[:allow_none]
|
283
308
|
raise "every player has to have a rank" unless ranks.size == @player.size
|
284
|
-
|
285
|
-
# The higest and lowest ranks respectively should be 1 and the number of players.
|
286
309
|
by_rank = @player.values.sort{ |a,b| a.rank <=> b.rank}
|
287
310
|
raise "the highest rank must be 1" unless by_rank[0].rank == 1
|
288
311
|
raise "the lowest rank must be #{ranks.size}" unless by_rank[-1].rank == ranks.size
|
289
|
-
|
290
|
-
# If scores are ordered by ranks, they should go from highest to lowest.
|
291
312
|
if by_rank.size > 1
|
292
313
|
(1..by_rank.size-1).each do |i|
|
293
314
|
p1 = by_rank[i-1]
|
data/lib/tournament_krause.rb
CHANGED
@@ -14,6 +14,7 @@ Suppose, for example, that the following data is the file <em>tournament.tab</em
|
|
14
14
|
032 IRL
|
15
15
|
042 2009.09.09
|
16
16
|
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
17
|
+
132 09.09.09 09.09.10 09.09.11
|
17
18
|
001 1 w Mouse,Minerva 1900 USA 1234567 1928.05.15 1.0 2 2 b 0 3 w 1
|
18
19
|
001 2 m m Duck,Daffy 2200 IRL 7654321 1937.04.17 2.0 1 1 w 1 3 b 1
|
19
20
|
001 3 m g Mouse,Mickey 2600 USA 1726354 1928.05.15 0.0 3 1 b 0 2 w 0
|
@@ -29,9 +30,13 @@ ICU::Tournament (rather than <em>nil</em>, which indicates an error). In this ex
|
|
29
30
|
|
30
31
|
tournament.name # => "Fantasy Tournament"
|
31
32
|
tournament.start # => "2009-09-09"
|
32
|
-
tournament.rounds # => 3
|
33
33
|
tournament.fed # => "IRL"
|
34
34
|
tournament.players.size # => 9
|
35
|
+
|
36
|
+
Some values, not explicitly set in the file, are deduced:
|
37
|
+
|
38
|
+
tournament.rounds # => 3
|
39
|
+
tournament.finish # => "2009-09-11"
|
35
40
|
|
36
41
|
A player can be retrieved from the tournament via the _players_ array or by sending a valid player number to the _player_ method.
|
37
42
|
|
@@ -72,7 +77,7 @@ The following lists Krause data identification numbers, their description and, w
|
|
72
77
|
[102 Arbiter(s)] Get or set with -arbiter_. Free text.
|
73
78
|
[112 Deputy(ies)] Get or set with _deputy_. Free text.
|
74
79
|
[122 Time control] Get or set with _time_control_. Free text.
|
75
|
-
[132 Round dates]
|
80
|
+
[132 Round dates] Get an array of dates using _round_dates_ or one specific round date by calling _round_date_ with a round number.
|
76
81
|
|
77
82
|
=end
|
78
83
|
|
@@ -131,7 +136,7 @@ The following lists Krause data identification numbers, their description and, w
|
|
131
136
|
when '102' then @tournament.arbiter = @data # arbiter(s)
|
132
137
|
when '112' then @tournament.deputy = @data # deputy(ies)
|
133
138
|
when '122' then @tournament.time_control = @data # time control
|
134
|
-
when '132' then
|
139
|
+
when '132' then add_round_dates # round dates
|
135
140
|
else raise "invalid DIN #{din}"
|
136
141
|
end
|
137
142
|
rescue => err
|
@@ -172,6 +177,11 @@ The following lists Krause data identification numbers, their description and, w
|
|
172
177
|
krause << "102 #{t.arbiter}\n" if t.arbiter
|
173
178
|
krause << "112 #{t.deputy}\n" if t.deputy
|
174
179
|
krause << "122 #{t.time_control}\n" if t.time_control
|
180
|
+
if t.round_dates.size > 0
|
181
|
+
krause << "132 #{' ' * 85}"
|
182
|
+
t.round_dates.each{ |d| krause << d.sub(/^../, ' ') }
|
183
|
+
krause << "\n"
|
184
|
+
end
|
175
185
|
t.players.each{ |p| krause << p.to_krause(@tournament.rounds) }
|
176
186
|
krause
|
177
187
|
end
|
@@ -235,6 +245,16 @@ The following lists Krause data identification numbers, their description and, w
|
|
235
245
|
@results << [@lineno, player, data, result]
|
236
246
|
result.points
|
237
247
|
end
|
248
|
+
|
249
|
+
def add_round_dates
|
250
|
+
raise "round dates record less than minimum length" if @line.length < 99
|
251
|
+
index = 87
|
252
|
+
while @data.length >= index + 8
|
253
|
+
date = @data[index, 8].strip
|
254
|
+
@tournament.add_round_date("20#{date}") unless date == ''
|
255
|
+
index+= 10
|
256
|
+
end
|
257
|
+
end
|
238
258
|
|
239
259
|
def add_comment
|
240
260
|
@comments << @line
|
@@ -29,7 +29,7 @@ module ICU
|
|
29
29
|
022 Las Vegas
|
30
30
|
032 USA
|
31
31
|
042 2008.06.07
|
32
|
-
052 2008.06.
|
32
|
+
052 2008.06.09
|
33
33
|
062 3
|
34
34
|
072 3
|
35
35
|
082 1
|
@@ -40,7 +40,7 @@ module ICU
|
|
40
40
|
013 Coaching Team 1 2
|
41
41
|
0 1 2 3 4 5 6 7 8 9 0 1 2
|
42
42
|
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
43
|
-
132 08.
|
43
|
+
132 08.06.07 08.06.08 08.06.09
|
44
44
|
001 1 w Ui Laighleis,Gearoidin 1985 IRL 2501171 1964.06.10 1.0 2 2 b 0 3 w 1
|
45
45
|
001 2 m m Orr,Mark 2258 IRL 2500035 1955.11.09 2.0 1 1 w 1 3 b 1
|
46
46
|
001 3 m g Bologan,Viktor 2663 MDA 13900048 1971.01.01 0.0 3 1 b 0 2 w 0
|
@@ -57,7 +57,7 @@ KRAUSE
|
|
57
57
|
|
58
58
|
it "should have start and end dates" do
|
59
59
|
@t.start.should == '2008-06-07'
|
60
|
-
@t.finish.should == '2008-06-
|
60
|
+
@t.finish.should == '2008-06-09'
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should have a number of rounds, a type and a time control" do
|
@@ -84,6 +84,10 @@ KRAUSE
|
|
84
84
|
check_results(3, 2, 0.0)
|
85
85
|
end
|
86
86
|
|
87
|
+
it "should have correct round dates" do
|
88
|
+
@t.round_dates.join('|').should == '2008-06-07|2008-06-08|2008-06-09'
|
89
|
+
end
|
90
|
+
|
87
91
|
it "the parser should retain comment lines" do
|
88
92
|
comments = <<COMMENTS
|
89
93
|
062 3
|
@@ -92,7 +96,6 @@ KRAUSE
|
|
92
96
|
013 Coaching Team 1 2
|
93
97
|
0 1 2 3 4 5 6 7 8 9 0 1 2
|
94
98
|
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
95
|
-
132 08.02.01 08.02.02 08.02.03
|
96
99
|
COMMENTS
|
97
100
|
@p.comments.should == comments
|
98
101
|
end
|
@@ -105,6 +108,7 @@ COMMENTS
|
|
105
108
|
032 IRL
|
106
109
|
042 2009.09.09
|
107
110
|
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
111
|
+
132 09.09.09 09.09.10 09.09.11
|
108
112
|
001 1 w Mouse,Minerva 1900 USA 1234567 1928.05.15 1.0 2 2 b 0 3 w 1
|
109
113
|
001 2 m m Duck,Daffy 2200 IRL 7654321 1937.04.17 2.0 1 1 w 1 3 b 1
|
110
114
|
001 3 m g Mouse,Mickey 2600 USA 1726354 1928.05.15 0.0 3 1 b 0 2 w 0
|
@@ -118,8 +122,10 @@ KRAUSE
|
|
118
122
|
@t.fed.should == 'IRL'
|
119
123
|
end
|
120
124
|
|
121
|
-
it "should have a
|
125
|
+
it "should have a various dates" do
|
122
126
|
@t.start.should == '2009-09-09'
|
127
|
+
@t.finish.should == '2009-09-11'
|
128
|
+
@t.round_dates.join('|').should == '2009-09-09|2009-09-10|2009-09-11'
|
123
129
|
end
|
124
130
|
|
125
131
|
it "should have a number of rounds" do
|
@@ -156,6 +162,7 @@ KRAUSE
|
|
156
162
|
102 Hans Scmidt
|
157
163
|
112 Gerry Graham, Herbert Scarry
|
158
164
|
122 60 in 2hr, 30 in 1hr, rest in 1hr
|
165
|
+
132 08-06-07 08-06-08 08-06-09
|
159
166
|
001 1 w Ui Laighleis,Gearoidin 1985 IRL 2501171 1964-06-10 2.0 2 2 b 0 3 w + 4 b 1
|
160
167
|
001 2 m m Orr,Mark 2258 IRL 2500035 1955-11-09 2.5 1 1 w 1 0000 - = 3 b 1
|
161
168
|
001 3 m g Bologan,Viktor 2663 MDA 13900048 1971-01-01 0.0 4 1 b - 2 w 0
|
data/spec/tournament_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
2
2
|
|
3
3
|
module ICU
|
4
4
|
describe Tournament do
|
5
|
-
context "a
|
5
|
+
context "a basic tournament" do
|
6
6
|
it "has a name, start date, some players and some results" do
|
7
7
|
lambda do
|
8
8
|
t = Tournament.new('Bangor Bash', '2009-11-09')
|
@@ -12,134 +12,129 @@ module ICU
|
|
12
12
|
t.add_result(Result.new(1, 1, '=', :opponent => 2, :colour => 'W'))
|
13
13
|
t.add_result(Result.new(2, 2, 'L', :opponent => 3, :colour => 'W'))
|
14
14
|
t.add_result(Result.new(3, 3, 'W', :opponent => 1, :colour => 'W'))
|
15
|
+
t.validate!
|
15
16
|
end.should_not raise_error
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
-
# Tournament name.
|
19
|
+
|
20
20
|
context "name" do
|
21
21
|
before(:each) do
|
22
22
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09')
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
it "must be specified in constructor" do
|
26
26
|
@t.name.should == 'Edinburgh Masters'
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it "can be replaced by accessor" do
|
30
30
|
@t.name = 'Bangor Bashers'
|
31
31
|
@t.name.should == 'Bangor Bashers'
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
it "should not be blank or without letters" do
|
35
35
|
lambda { Tournament.new(' ', '2009-11-09') }.should raise_error(/invalid.*name/)
|
36
36
|
lambda { @t.name = '333' }.should raise_error(/invalid.*name/)
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
40
|
-
# Tournament city.
|
39
|
+
|
41
40
|
context "city" do
|
42
41
|
before(:each) do
|
43
42
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09', :city => 'Edinburgh')
|
44
43
|
end
|
45
|
-
|
44
|
+
|
46
45
|
it "may be specified in constructor" do
|
47
46
|
@t.city.should == 'Edinburgh'
|
48
47
|
end
|
49
|
-
|
48
|
+
|
50
49
|
it "can be replaced by accessor" do
|
51
50
|
@t.city = 'Glasgow'
|
52
51
|
@t.city.should == 'Glasgow'
|
53
52
|
end
|
54
|
-
|
53
|
+
|
55
54
|
it "can be set to nil" do
|
56
55
|
@t.city = ''
|
57
56
|
@t.city.should be_nil
|
58
57
|
end
|
59
|
-
|
58
|
+
|
60
59
|
it "should not be without letters if set" do
|
61
60
|
lambda { @t.city = '123' }.should raise_error(/invalid.*city/)
|
62
61
|
end
|
63
62
|
end
|
64
63
|
|
65
|
-
# Tournament federation.
|
66
64
|
context "federation" do
|
67
65
|
before(:each) do
|
68
66
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09', :fed => 'SCO')
|
69
67
|
end
|
70
|
-
|
68
|
+
|
71
69
|
it "may be specified in constructor" do
|
72
70
|
@t.fed.should == 'SCO'
|
73
71
|
end
|
74
|
-
|
72
|
+
|
75
73
|
it "can be replaced by accessor" do
|
76
74
|
@t.fed = 'IRL'
|
77
75
|
@t.fed.should == 'IRL'
|
78
76
|
end
|
79
|
-
|
77
|
+
|
80
78
|
it "can be set to nil" do
|
81
79
|
@t.fed = ''
|
82
80
|
@t.fed.should be_nil
|
83
81
|
end
|
84
|
-
|
82
|
+
|
85
83
|
it "three letters will automatically be upcased" do
|
86
84
|
@t.fed = 'rus'
|
87
85
|
@t.fed.should == 'RUS'
|
88
86
|
end
|
89
|
-
|
87
|
+
|
90
88
|
it "should not be without letters if set" do
|
91
89
|
lambda { @t.fed = '123' }.should raise_error(/invalid.*federation/)
|
92
90
|
end
|
93
91
|
end
|
94
92
|
|
95
|
-
# Tournament start date.
|
96
93
|
context "start date" do
|
97
94
|
before(:each) do
|
98
95
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09')
|
99
96
|
end
|
100
|
-
|
97
|
+
|
101
98
|
it "must be specified in constructor" do
|
102
99
|
@t.start.should == '2009-11-09'
|
103
100
|
end
|
104
|
-
|
101
|
+
|
105
102
|
it "can be replaced by accessor" do
|
106
103
|
@t.start = '16th June 2010'
|
107
104
|
@t.start.should == '2010-06-16'
|
108
105
|
end
|
109
|
-
|
106
|
+
|
110
107
|
it "should be a valid date" do
|
111
108
|
lambda { Tournament.new('Edinburgh Masters', ' ') }.should raise_error(/invalid.*date/)
|
112
109
|
lambda { @t.start = 'X' }.should raise_error(/invalid.*date/)
|
113
110
|
end
|
114
111
|
end
|
115
|
-
|
116
|
-
# Tournament finish date.
|
112
|
+
|
117
113
|
context "finish date" do
|
118
114
|
before(:each) do
|
119
115
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09', :finish => '12th November 2009')
|
120
116
|
end
|
121
|
-
|
117
|
+
|
122
118
|
it "may be specified in constructor" do
|
123
119
|
@t.finish.should == '2009-11-12'
|
124
120
|
end
|
125
|
-
|
121
|
+
|
126
122
|
it "can be replaced by accessor" do
|
127
123
|
@t.finish = '16th December 2009'
|
128
124
|
@t.finish.should == '2009-12-16'
|
129
125
|
end
|
130
|
-
|
126
|
+
|
131
127
|
it "can be set to nil" do
|
132
128
|
@t.finish = ''
|
133
129
|
@t.finish.should be_nil
|
134
130
|
end
|
135
|
-
|
131
|
+
|
136
132
|
it "should be a valid date" do
|
137
133
|
lambda { Tournament.new('Edinburgh Masters', '2009-11-09', :finish => 'next week') }.should raise_error(/invalid.*date/)
|
138
134
|
lambda { @t.finish = 'X' }.should raise_error(/invalid.*date/)
|
139
135
|
end
|
140
136
|
end
|
141
|
-
|
142
|
-
# Number of rounds.
|
137
|
+
|
143
138
|
context "rounds" do
|
144
139
|
it "defaults to nil" do
|
145
140
|
Tournament.new('Edinburgh Masters', '2009-11-09').rounds.should be_nil
|
@@ -151,8 +146,24 @@ module ICU
|
|
151
146
|
lambda { Tournament.new('Edinburgh Masters', '2009-11-09', :rounds => ' 0 ') }.should raise_error(/invalid.*rounds/)
|
152
147
|
end
|
153
148
|
end
|
154
|
-
|
155
|
-
|
149
|
+
|
150
|
+
context "round date" do
|
151
|
+
before(:each) do
|
152
|
+
@t = Tournament.new('Edinburgh Masters', '2009-11-09')
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should default to none" do
|
156
|
+
@t.round_dates.size.should == 0
|
157
|
+
end
|
158
|
+
|
159
|
+
it "can be added one by one in any order" do
|
160
|
+
@t.add_round_date('2009-11-11')
|
161
|
+
@t.add_round_date('09/11/2009')
|
162
|
+
@t.add_round_date('10th November 2009')
|
163
|
+
@t.round_dates.join('|').should == '2009-11-09|2009-11-10|2009-11-11'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
156
167
|
context "site" do
|
157
168
|
it "defaults to nil" do
|
158
169
|
Tournament.new('Edinburgh Masters', '2009-11-09').site.should be_nil
|
@@ -164,20 +175,19 @@ module ICU
|
|
164
175
|
lambda { Tournament.new('Edinburgh Masters', '2009-11-09', :site => 'X') }.should raise_error(/invalid.*site/)
|
165
176
|
end
|
166
177
|
end
|
167
|
-
|
168
|
-
# Type, arbiter, deputy and time control.
|
178
|
+
|
169
179
|
context "type, arbiter, deputy and time control" do
|
170
180
|
before(:each) do
|
171
181
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09', :type => 'Swiss', :arbiter => 'Gerry Graham', :deputy => 'Herbert Scarry', :time_control => '120 minutes')
|
172
182
|
end
|
173
|
-
|
183
|
+
|
174
184
|
it "may be specified in constructor" do
|
175
185
|
@t.type.should == 'Swiss'
|
176
186
|
@t.arbiter.should == 'Gerry Graham'
|
177
187
|
@t.deputy.should == 'Herbert Scarry'
|
178
188
|
@t.time_control.should == '120 minutes'
|
179
189
|
end
|
180
|
-
|
190
|
+
|
181
191
|
it "can be replaced by accessor" do
|
182
192
|
@t.type = 'all-play-all'
|
183
193
|
@t.type.should == 'all-play-all'
|
@@ -188,7 +198,7 @@ module ICU
|
|
188
198
|
@t.time_control = '90 minutes'
|
189
199
|
@t.time_control.should == '90 minutes'
|
190
200
|
end
|
191
|
-
|
201
|
+
|
192
202
|
it "can be set to nil" do
|
193
203
|
@t.type = ''
|
194
204
|
@t.type.should be_nil
|
@@ -199,7 +209,7 @@ module ICU
|
|
199
209
|
@t.time_control = ''
|
200
210
|
@t.time_control.should be_nil
|
201
211
|
end
|
202
|
-
|
212
|
+
|
203
213
|
it "should be valid" do
|
204
214
|
lambda { @t.type = '123' }.should raise_error(/invalid.*type/)
|
205
215
|
lambda { @t.arbiter = '123' }.should raise_error(/invalid.*arbiter/)
|
@@ -207,18 +217,17 @@ module ICU
|
|
207
217
|
lambda { @t.time_control = 'abc' }.should raise_error(/invalid.*time control/)
|
208
218
|
end
|
209
219
|
end
|
210
|
-
|
211
|
-
# Tournament players.
|
220
|
+
|
212
221
|
context "players" do
|
213
222
|
before(:each) do
|
214
223
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09')
|
215
224
|
end
|
216
|
-
|
225
|
+
|
217
226
|
it "should have unique numbers" do
|
218
227
|
@t.add_player(Player.new('Mark', 'Orr', 1))
|
219
228
|
lambda { @t.add_player(Player.new('Bobby', 'Fischer', 1)) }.should raise_error(/player.*unique/)
|
220
229
|
end
|
221
|
-
|
230
|
+
|
222
231
|
it "can be added one at a time" do
|
223
232
|
@t.add_player(Player.new('Mark', 'Orr', -1))
|
224
233
|
@t.add_player(Player.new('Gary', 'Kasparov', -2))
|
@@ -227,8 +236,7 @@ module ICU
|
|
227
236
|
@t.player(-1).first_name.should == 'Mark'
|
228
237
|
end
|
229
238
|
end
|
230
|
-
|
231
|
-
# Tournament results.
|
239
|
+
|
232
240
|
context "results" do
|
233
241
|
before(:each) do
|
234
242
|
@t = Tournament.new('Edinburgh Masters', '2009-11-09', :rounds => 3)
|
@@ -236,7 +244,7 @@ module ICU
|
|
236
244
|
@t.add_player(@gary = Player.new('Gary', 'Kasparov', 2))
|
237
245
|
@t.add_player(@boby = Player.new('Bobby', 'Fischer', 3))
|
238
246
|
end
|
239
|
-
|
247
|
+
|
240
248
|
it "can be added one at a time" do
|
241
249
|
@t.add_result(Result.new(1, 1, 'W', :opponent => 2))
|
242
250
|
@t.add_result(Result.new(2, 2, 'D', :opponent => 3))
|
@@ -248,7 +256,7 @@ module ICU
|
|
248
256
|
@boby.results.size.should == 2
|
249
257
|
@boby.points.should == 0.5
|
250
258
|
end
|
251
|
-
|
259
|
+
|
252
260
|
it "can be added symmetrically or asymmetrically with respect to rateability" do
|
253
261
|
@t.add_result(Result.new(1, 1, 'W', :opponent => 2))
|
254
262
|
@mark.results[0].rateable.should be_true
|
@@ -257,20 +265,20 @@ module ICU
|
|
257
265
|
@mark.results[1].rateable.should be_true
|
258
266
|
@boby.results[0].rateable.should be_false
|
259
267
|
end
|
260
|
-
|
268
|
+
|
261
269
|
it "should have a defined player" do
|
262
270
|
lambda { @t.add_result(Result.new(1, 4, 'L', :opponent => 1)) }.should raise_error(/player.*exist/)
|
263
271
|
end
|
264
|
-
|
272
|
+
|
265
273
|
it "should have a defined opponent" do
|
266
274
|
lambda { @t.add_result(Result.new(1, 1, 'W', :opponent => 4)) }.should raise_error(/opponent.*exist/)
|
267
275
|
end
|
268
|
-
|
276
|
+
|
269
277
|
it "should be consistent with the tournament's number of rounds" do
|
270
278
|
lambda { @t.add_result(Result.new(4, 1, 'W', :opponent => 2)) }.should raise_error(/round/)
|
271
279
|
end
|
272
280
|
end
|
273
|
-
|
281
|
+
|
274
282
|
context "finding players" do
|
275
283
|
before(:all) do
|
276
284
|
@t = Tournament.new('Bangor Bash', '2009-11-09')
|
@@ -278,7 +286,7 @@ module ICU
|
|
278
286
|
@t.add_player(Player.new('Garry', 'Gary Kasparov', 2, :fed => 'RUS'))
|
279
287
|
@t.add_player(Player.new('Mark', 'Orr', 3, :fed => 'IRL'))
|
280
288
|
end
|
281
|
-
|
289
|
+
|
282
290
|
it "should find players based on loose equality" do
|
283
291
|
@t.find_player(Player.new('Mark', 'Orr', 4, :fed => 'IRL')).num.should == 3
|
284
292
|
@t.find_player(Player.new('Mark', 'Orr', 4, :fed => 'USA')).should be_nil
|
@@ -286,5 +294,76 @@ module ICU
|
|
286
294
|
@t.find_player(Player.new('John', 'Orr', 4, :fed => 'IRL')).should be_nil
|
287
295
|
end
|
288
296
|
end
|
297
|
+
|
298
|
+
context "validation" do
|
299
|
+
before(:each) do
|
300
|
+
@t = Tournament.new('Edinburgh Masters', '2009-11-09')
|
301
|
+
@t.add_player(@mark = Player.new('Mark', 'Orr', 1))
|
302
|
+
@t.add_player(@gary = Player.new('Gary', 'Kasparov', 2))
|
303
|
+
@t.add_player(@boby = Player.new('Bobby', 'Fischer', 3))
|
304
|
+
@t.add_result(Result.new(1, 1, 'W', :opponent => 2))
|
305
|
+
@t.add_result(Result.new(2, 2, 'W', :opponent => 3))
|
306
|
+
@t.add_result(Result.new(3, 3, 'L', :opponent => 1))
|
307
|
+
@t.add_round_date('2009-11-09')
|
308
|
+
@t.add_round_date('2009-11-10')
|
309
|
+
@t.add_round_date('2009-11-11')
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should be valid" do
|
313
|
+
@t.invalid.should be_false
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should have side effect of setting number of rounds" do
|
317
|
+
@t.rounds.should be_nil
|
318
|
+
@t.invalid
|
319
|
+
@t.rounds.should == 3
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should detect an inconsistent start date" do
|
323
|
+
@t.start = '2009-11-10'
|
324
|
+
lambda { @t.validate! }.should raise_error(/first round.*before.*start/)
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should detect an inconsistent finish date" do
|
328
|
+
@t.finish = '2009-11-10'
|
329
|
+
lambda { @t.validate! }.should raise_error(/last round.*after.*end/)
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should have side effect of setting missing finish date" do
|
333
|
+
@t.finish.should be_nil
|
334
|
+
@t.invalid
|
335
|
+
@t.finish.should == '2009-11-11'
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should detect inconsistent round dates" do
|
339
|
+
@t.add_round_date('2009-11-12')
|
340
|
+
lambda { @t.validate! }.should raise_error(/round dates.*match.*rounds/)
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should have the side effect of providing missing ranks if the rerank option is set" do
|
344
|
+
@t.players.select{ |p| p.rank }.size.should == 0
|
345
|
+
@t.invalid(:rerank => true)
|
346
|
+
@t.player(1).rank.should == 1
|
347
|
+
@t.player(2).rank.should == 2
|
348
|
+
@t.player(3).rank.should == 3
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should have the side effect of correcting bad ranks if the rerank option is set" do
|
352
|
+
@t.player(1).rank = 2
|
353
|
+
@t.player(2).rank = 1
|
354
|
+
@t.player(3).rank = 3
|
355
|
+
@t.invalid(:rerank => true)
|
356
|
+
@t.player(1).rank.should == 1
|
357
|
+
@t.player(2).rank.should == 2
|
358
|
+
@t.player(3).rank.should == 3
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should detect missranked players" do
|
362
|
+
@t.player(1).rank = 2
|
363
|
+
@t.player(2).rank = 1
|
364
|
+
@t.player(3).rank = 3
|
365
|
+
lambda { @t.validate! }.should raise_error(/player 2.*above.*player 1/)
|
366
|
+
end
|
367
|
+
end
|
289
368
|
end
|
290
369
|
end
|