rrschedule 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.3
data/lib/rrschedule.rb CHANGED
@@ -89,7 +89,7 @@ module RRSchedule
89
89
  self.gamedays.each do |gd|
90
90
  res << gd.date.strftime("%Y-%m-%d") + "\n"
91
91
  res << "==========\n"
92
- gd.games.each do |g|
92
+ gd.games.sort{|g1,g2| g1.gt == g2.gt ? g1.ps <=> g2.ps : g1.gt <=> g2.gt}.each do |g|
93
93
  res << "#{g.ta.to_s} VS #{g.tb.to_s} on playing surface #{g.ps} at #{g.gt.strftime("%I:%M %p")}\n"
94
94
  end
95
95
  res << "\n"
@@ -129,42 +129,19 @@ module RRSchedule
129
129
  end
130
130
 
131
131
  #Dispatch games according to available playing surfaces and game times
132
- #The flat schedule contains "place holders" for the actual games. Each row contains
133
- #a game date, a game time and a playing surface. We then process our rounds one by one
134
- #and we put each matchup in the next available slot of the flat schedule
135
132
  def dispatch_games(rounds)
136
- teams_day = {}
137
- flat_schedule = generate_flat_schedule
138
-
139
133
  rounds_copy = Marshal.load(Marshal.dump(rounds)) #deep clone
140
- cur_flight_index = i = 0
134
+ cur_flight_index = 0
141
135
 
142
136
  while !rounds_copy.flatten.empty? do
143
137
  cur_round = rounds_copy[cur_flight_index].shift
144
-
145
138
  #process the next round in the current flight
146
139
  if cur_round
147
- cur_round.games.shuffle.each do |game|
148
- unless [game.team_a,game.team_b].include?(:dummy)
149
- if teams_day[flat_schedule[i][:gamedate]] && (teams_day[flat_schedule[i][:gamedate]].include?(game.team_a) || teams_day[flat_schedule[i][:gamedate]].include?(game.team_b))
150
- #team is already playing this day. This can happen if we have flights with different number of teams in it.
151
- gamedate = flat_schedule[i][:gamedate]
152
- while flat_schedule[i] && flat_schedule[i][:gamedate] == gamedate do
153
- i += 1
154
- end
155
- end
156
-
157
- flat_schedule[i][:team_a] = game.team_a
158
- flat_schedule[i][:team_b] = game.team_b
159
- teams_day[flat_schedule[i][:gamedate]] ||= []
160
- teams_day[flat_schedule[i][:gamedate]] << game.team_a
161
- teams_day[flat_schedule[i][:gamedate]] << game.team_b
162
- i += 1
163
- end
140
+ cur_round.games.each do |game|
141
+ dispatch_game(game) unless [game.team_a,game.team_b].include?(:dummy)
164
142
  end
165
143
  end
166
144
 
167
-
168
145
  if cur_flight_index == @flights.size-1
169
146
  cur_flight_index = 0
170
147
  else
@@ -172,8 +149,8 @@ module RRSchedule
172
149
  end
173
150
  end
174
151
 
175
- #We group our flat schedule by gameday
176
- s=flat_schedule.group_by{|fs| fs[:gamedate]}.sort
152
+ #We group our schedule by gameday
153
+ s=@schedule.group_by{|fs| fs[:gamedate]}.sort
177
154
  s.each do |gamedate,gms|
178
155
  games = []
179
156
  gms.each do |gm|
@@ -186,57 +163,113 @@ module RRSchedule
186
163
  end
187
164
  self.gamedays << Gameday.new(:date => gamedate, :games => games)
188
165
  end
189
- self.gamedays.each { |gd| gd.games.reject! {|g| g.team_a.nil?}}
190
166
  end
191
167
 
192
168
 
193
- def generate_flat_schedule
194
- flat_schedule = []
195
- games_left = max_games_per_day = day_game_ctr = rule_ctr = 0
196
-
197
- #determine first rule based on the nearest gameday
198
- cur_rule = @rules.select{|r| r.wday >= self.start_date.wday}.first || @rules.first
199
- cur_rule_index = @rules.index(cur_rule)
200
- cur_date = next_game_date(self.start_date,cur_rule.wday)
201
-
202
- @flights.each do |flight|
203
- games_left += @cycles * (flight.include?(:dummy) ? ((flight.size-1)/2.0)*(flight.size-2) : (flight.size/2)*(flight.size-1))
204
- max_games_per_day += (flight.include?(:dummy) ? ((flight.size-2)/2.0) : (flight.size-1)/2.0).ceil
169
+ def dispatch_game(game)
170
+ @cur_rule ||= @rules.select{|r| r.wday >= self.start_date.wday}.first || @rules.first
171
+ @cur_rule_index ||= @rules.index(@cur_rule)
172
+
173
+ @gt_stack ||= @cur_rule.gt.clone
174
+ @ps_stack ||= @cur_rule.ps.clone.shuffle
175
+
176
+ @cur_gt ||= @gt_stack.shift
177
+ @cur_ps ||= @ps_stack.shift
178
+ @cur_date ||= next_game_date(self.start_date,@cur_rule.wday)
179
+ @schedule ||= []
180
+
181
+ #if one of the team has already plays at this gamedate, we change rule
182
+ if @schedule.size>0
183
+ games_this_date = @schedule.select{|v| v[:gamedate] == @cur_date}
184
+ if games_this_date.select{|g| [game.team_a,game.team_b].include?(g[:team_a]) || [game.team_a,game.team_b].include?(g[:team_b])}.size >0
185
+ @cur_rule_index = (@cur_rule_index < @rules.size-1) ? @cur_rule_index+1 : 0
186
+ @cur_rule = @rules[@cur_rule_index]
187
+ @gt_stack = @cur_rule.gt.clone
188
+ @ps_stack = @cur_rule.ps.clone.shuffle
189
+ @cur_gt = @gt_stack.shift
190
+ @cur_ps = @ps_stack.shift
191
+ @cur_date = next_game_date(@cur_date+=1,@cur_rule.wday)
192
+ end
205
193
  end
206
194
 
195
+ @schedule << {:team_a => game.team_a, :team_b => game.team_b, :gamedate => @cur_date, :ps => @cur_ps, :gt => @cur_gt}
207
196
 
208
- #while there are games to process...
209
- while games_left > 0 do
197
+ if !@ps_stack.empty?
198
+ @cur_ps = @ps_stack.shift
199
+ else
200
+ if !@gt_stack.empty?
201
+ @cur_gt = @gt_stack.shift
202
+ @ps_stack = @cur_rule.ps.clone.shuffle; @cur_ps = @ps_stack.shift
203
+ else
204
+ #PS and GT stack empty... we go to the next rule
205
+ if @cur_rule_index < @rules.size-1
206
+ @cur_rule_index += 1
207
+ #Go to the next date (except if the new rule is for the same weekday)
208
+ @cur_date = next_game_date(@cur_date+=1,@cur_rule.wday) if @cur_rule.wday != @rules[@cur_rule_index].wday
209
+ else
210
+ @cur_rule_index = 0
211
+ @cur_date = next_game_date(@cur_date+=1,@cur_rule.wday)
212
+ end
213
+ @cur_rule = @rules[@cur_rule_index]
214
+ @gt_stack = @cur_rule.gt.clone; @cur_gt = @gt_stack.shift
215
+ @ps_stack = @cur_rule.ps.clone.shuffle; @cur_ps = @ps_stack.shift
216
+ end
217
+ end
210
218
 
211
- #add all possible games based on the current rule
212
- cur_rule.gt.each do |gt|
213
- cur_rule.ps.each do |ps|
219
+ end
214
220
 
215
- #if there are more physical resources (playing surfaces and game times) for a given day than
216
- #we need, we don't use them all (or else some teams would play twice on a single day)
217
- if day_game_ctr <= max_games_per_day-1
218
- flat_schedule << {:gamedate => cur_date, :gt => gt, :ps => ps}
219
- games_left -= 1; day_game_ctr += 1
220
- end
221
- end
221
+ def place_game(game)
222
+ @cur_rule ||= @rules.select{|r| r.wday >= self.start_date.wday}.first || @rules.first
223
+
224
+ @cur_rule_index ||= @rules.index(@cur_rule)
225
+ @cur_gt_index ||= 0
226
+ @cur_ps_index ||= 0
227
+
228
+ @cur_gt = @cur_rule.gt[@cur_gt_index]
229
+ @cur_ps = @cur_rule.ps[@cur_ps_index]
230
+ @cur_date ||= next_game_date(self.start_date,@cur_rule.wday)
231
+ @schedule ||= []
232
+
233
+ #if one of the team has already plays at this gamedate, we change rule
234
+ if @schedule.size>0
235
+ games_this_date = @schedule.select{|v| v[:gamedate] == @cur_date}
236
+ if games_this_date.select{|g| [game.team_a,game.team_b].include?(g[:team_a]) || [game.team_a,game.team_b].include?(g[:team_b])}.size >0
237
+ @cur_rule_index = (@cur_rule_index < @rules.size-1) ? @cur_rule_index+1 : 0
238
+ @cur_rule = @rules[@cur_rule_index]
239
+ @cur_ps_index=0
240
+ @cur_gt_index=0
241
+ @cur_ps = @cur_rule.ps.first
242
+ @cur_gt = @cur_rule.gt.first
243
+ @cur_date = next_game_date(@cur_date+=1,@cur_rule.wday)
222
244
  end
245
+ end
223
246
 
224
- last_rule = cur_rule
225
- last_date = cur_date
247
+ @schedule << {:team_a => game.team_a, :team_b => game.team_b, :gamedate => @cur_date, :ps => @cur_ps, :gt => @cur_gt}
226
248
 
227
- #Advance to the next rule (if we're at the last one, we go back to the first)
228
- cur_rule_index = (cur_rule_index == @rules.size-1) ? 0 : cur_rule_index + 1
229
- cur_rule = @rules[cur_rule_index]
249
+ if @cur_ps_index < @cur_rule.ps.size-1
250
+ @cur_ps_index += 1
251
+ else
252
+ @cur_ps_index = 0
230
253
 
231
- #Go to the next date (except if the new rule is for the same weekday)
232
- if cur_rule.wday != last_rule.wday || cur_rule_index == 0
233
- cur_date = next_game_date(cur_date+=1,cur_rule.wday)
234
- day_game_ctr = 0
254
+ if @cur_gt_index < @cur_rule.gt.size-1
255
+ @cur_gt_index += 1
256
+ else
257
+ @cur_gt_index = 0
258
+
259
+ if @cur_rule_index < @rules.size-1
260
+ @cur_rule_index += 1
261
+ #Go to the next date (except if the new rule is for the same weekday)
262
+ @cur_date = next_game_date(@cur_date+=1,@cur_rule.wday) if @cur_rule.wday != @rules[@cur_rule_index].wday
263
+ else
264
+ @cur_rule_index = 0
265
+ @cur_date = next_game_date(@cur_date+=1,@cur_rule.wday)
266
+ end
267
+ @cur_rule = @rules[@cur_rule_index]
235
268
  end
236
269
  end
237
- flat_schedule
238
270
  end
239
271
 
272
+
240
273
  #get the next gameday
241
274
  def next_game_date(dt,wday)
242
275
  dt += 1 until wday == dt.wday && !self.exclude_dates.include?(dt)
@@ -142,8 +142,8 @@ class TestRrschedule < Test::Unit::TestCase
142
142
  @s = Schedule.new
143
143
  @s.teams = [%w(a1 a2 a3 a4 a5 a6 a7 a8), %w(b1 b2 b3 b4 b5 b6 b7 b8)]
144
144
  @s.rules = [
145
- Rule.new(:wday => 4, :gt => ["7:00PM"], :ps => %w(field#1 field#2)),
146
- Rule.new(:wday => 4, :gt => ["9:00PM"], :ps => %w(field#1 field#2 field#3))
145
+ Rule.new(:wday => 4, :gt => ["7:00PM"], :ps => %w(field1 field2)),
146
+ Rule.new(:wday => 4, :gt => ["9:00PM"], :ps => %w(field1 field2 field3))
147
147
  ]
148
148
  @s.start_date = Date.parse("2011/01/27")
149
149
  @s.generate
@@ -158,11 +158,11 @@ class TestRrschedule < Test::Unit::TestCase
158
158
  #the last one because it might not be full (round-robin over)
159
159
  if i<@s.gamedays.size-1
160
160
  assert_equal 5, gd.games.size
161
- assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("7:00PM") && g.playing_surface == "field#1"}.size
162
- assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("7:00PM") && g.playing_surface == "field#2"}.size
163
- assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("9:00PM") && g.playing_surface == "field#1"}.size
164
- assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("9:00PM") && g.playing_surface == "field#2"}.size
165
- assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("9:00PM") && g.playing_surface == "field#3"}.size
161
+ assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("7:00PM") && g.playing_surface == "field1"}.size
162
+ assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("7:00PM") && g.playing_surface == "field2"}.size
163
+ assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("9:00PM") && g.playing_surface == "field1"}.size
164
+ assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("9:00PM") && g.playing_surface == "field2"}.size
165
+ assert_equal 1, gd.games.select{|g| g.game_time == DateTime.parse("9:00PM") && g.playing_surface == "field3"}.size
166
166
  cur_date += 7
167
167
  end
168
168
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rrschedule
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 2
10
- version: 0.2.2
9
+ - 3
10
+ version: 0.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - flamontagne
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-17 00:00:00 -05:00
18
+ date: 2011-02-18 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency