rrschedule 0.2.2 → 0.2.3

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/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