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.
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 3
4
- :patch: 4
4
+ :patch: 5
@@ -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 message.
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 (only if the _rank_ or _rerank_ option is set)
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
- Both messages are capable of taking the following boolean valued hash options:
48
+ Side effects of calling _validate!_ or _invalid_ include:
49
49
 
50
- * _rank_ - check the player ranks
51
- * _rerank_ - check the player ranks and automatically repair if absent or not consistent
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
- For example:
53
+ If the _rerank_ option is set, as in this example:
54
54
 
55
- tournament.validate!(:rank => true)
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, :rounds, :site, :city, :fed, :type, :arbiter, :deputy, :time_control
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 numbers.
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
- check_ranks if options[:rank]
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]
@@ -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] Not implemented yet.
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 add_comment # round dates (not implemented yet)
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.10
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.02.01 08.02.02 08.02.03
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-10'
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 startdates" do
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
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  module ICU
4
4
  describe Tournament do
5
- context "a typical tournament" do
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
- # Web site.
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sanichi-chess_icu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Orr