rrschedule 0.2.9 → 0.2.10
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 +1 -1
- data/lib/rrschedule.rb +65 -86
- data/test_schedule.rb +19 -0
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.10
|
data/lib/rrschedule.rb
CHANGED
@@ -8,7 +8,7 @@ module RRSchedule
|
|
8
8
|
|
9
9
|
def initialize(params={})
|
10
10
|
@gamedays = []
|
11
|
-
self.teams = params[:teams]
|
11
|
+
self.teams = params[:teams] || []
|
12
12
|
self.cycles = params[:cycles] || 1
|
13
13
|
self.shuffle = params[:shuffle].nil? ? true : params[:shuffle]
|
14
14
|
self.exclude_dates = params[:exclude_dates] || []
|
@@ -21,33 +21,14 @@ module RRSchedule
|
|
21
21
|
def generate(params={})
|
22
22
|
raise "You need to specify at least 1 team" if @teams.nil? || @teams.empty?
|
23
23
|
raise "You need to specify at least 1 rule" if @rules.nil? || @rules.empty?
|
24
|
+
|
24
25
|
arrange_flights
|
26
|
+
init_stats
|
25
27
|
|
28
|
+
@gamedays = []; @rounds = []
|
26
29
|
|
27
|
-
@stats = {}
|
28
|
-
@teams.flatten.each do |t|
|
29
|
-
@stats[t] = {
|
30
|
-
:gt => {},
|
31
|
-
:ps => {}
|
32
|
-
}
|
33
|
-
|
34
|
-
@stats[t][:gt] = {}
|
35
|
-
all_gt.each do |gt|
|
36
|
-
@stats[t][:gt][gt] = 0
|
37
|
-
end
|
38
|
-
|
39
|
-
@stats[t][:ps] = {}
|
40
|
-
all_ps.each do |ps|
|
41
|
-
@stats[t][:ps][ps] = 0
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
@gamedays = []
|
46
|
-
@rounds = []
|
47
30
|
|
48
31
|
@flights.each_with_index do |teams,flight_id|
|
49
|
-
|
50
|
-
|
51
32
|
current_cycle = current_round = 0
|
52
33
|
teams = teams.sort_by{rand} if @shuffle
|
53
34
|
|
@@ -62,14 +43,11 @@ module RRSchedule
|
|
62
43
|
team_b = t.reverse!.shift
|
63
44
|
t.reverse!
|
64
45
|
|
46
|
+
x = [team_a,team_b].shuffle
|
65
47
|
|
66
|
-
|
67
|
-
|
68
|
-
matchup = {:team_a => x[0], :team_b => x[1], :home_team_index => self.teams.index(x[0])}
|
48
|
+
matchup = {:team_a => x[0], :team_b => x[1]}
|
69
49
|
games << matchup
|
70
50
|
end
|
71
|
-
#games = games.sort_by {|g| g[:home_team_index]}
|
72
|
-
|
73
51
|
#done processing round
|
74
52
|
|
75
53
|
current_round += 1
|
@@ -95,11 +73,7 @@ module RRSchedule
|
|
95
73
|
#have we completed a full round-robin for the current flight?
|
96
74
|
if current_round == teams.size-1
|
97
75
|
current_cycle += 1
|
98
|
-
|
99
|
-
if current_cycle < self.cycles
|
100
|
-
current_round = 0
|
101
|
-
teams = teams.sort_by{rand} if @shuffle
|
102
|
-
end
|
76
|
+
current_round = 0 if current_cycle < self.cycles
|
103
77
|
end
|
104
78
|
|
105
79
|
end until current_round == teams.size-1 && current_cycle==self.cycles
|
@@ -192,36 +166,6 @@ module RRSchedule
|
|
192
166
|
end
|
193
167
|
end
|
194
168
|
|
195
|
-
def get_best_gt(game)
|
196
|
-
x = {}
|
197
|
-
gt_left = @gt_ps_avail.reject{|k,v| v.empty?}
|
198
|
-
gt_left.each_key do |gt|
|
199
|
-
x[gt] = [
|
200
|
-
@stats[game.team_a][:gt][gt] + @stats[game.team_b][:gt][gt],
|
201
|
-
rand(1000)
|
202
|
-
]
|
203
|
-
end
|
204
|
-
x.sort_by{|k,v| [v[0],v[1]]}.first[0]
|
205
|
-
end
|
206
|
-
|
207
|
-
def get_best_ps(game,gt)
|
208
|
-
x = {}
|
209
|
-
@gt_ps_avail[gt].each do |ps|
|
210
|
-
x[ps] = [
|
211
|
-
@stats[game.team_a][:ps][ps] + @stats[game.team_b][:ps][ps],
|
212
|
-
rand(1000)
|
213
|
-
]
|
214
|
-
end
|
215
|
-
x.sort_by{|k,v| [v[0],v[1]]}.first[0]
|
216
|
-
end
|
217
|
-
|
218
|
-
def reset_resource_availability
|
219
|
-
@gt_ps_avail = {}
|
220
|
-
@cur_rule.gt.each do |gt|
|
221
|
-
@gt_ps_avail[gt] = @cur_rule.ps.clone
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
169
|
def dispatch_game(game)
|
226
170
|
if @cur_rule.nil?
|
227
171
|
@cur_rule = @rules.select{|r| r.wday >= self.start_date.wday}.first || @rules.first
|
@@ -232,12 +176,6 @@ module RRSchedule
|
|
232
176
|
@cur_gt = get_best_gt(game)
|
233
177
|
@cur_ps = get_best_ps(game,@cur_gt)
|
234
178
|
|
235
|
-
#increment the stats counters to lessen the chances that these teams plays on the same playing surface (or game time) too often
|
236
|
-
@stats[game.team_a][:gt][@cur_gt] += 1
|
237
|
-
@stats[game.team_a][:ps][@cur_ps] += 1
|
238
|
-
@stats[game.team_b][:gt][@cur_gt] += 1
|
239
|
-
@stats[game.team_b][:ps][@cur_ps] += 1
|
240
|
-
|
241
179
|
@cur_date ||= next_game_date(self.start_date,@cur_rule.wday)
|
242
180
|
@schedule ||= []
|
243
181
|
|
@@ -254,12 +192,14 @@ module RRSchedule
|
|
254
192
|
end
|
255
193
|
end
|
256
194
|
|
195
|
+
#We found our playing surface and game time, add the game in the schedule.
|
257
196
|
@schedule << {:team_a => game.team_a, :team_b => game.team_b, :gamedate => @cur_date, :ps => @cur_ps, :gt => @cur_gt}
|
258
|
-
|
197
|
+
update_team_stats(game,@cur_gt,@cur_ps)
|
198
|
+
update_resource_availability(@cur_gt,@cur_ps)
|
259
199
|
|
260
|
-
x = @gt_ps_avail.reject{|k,v| v.empty?}
|
261
200
|
|
262
|
-
#no resources left, change rule
|
201
|
+
#If no resources left, change rule
|
202
|
+
x = @gt_ps_avail.reject{|k,v| v.empty?}
|
263
203
|
if x.empty?
|
264
204
|
if @cur_rule_index < @rules.size-1
|
265
205
|
last_rule=@cur_rule
|
@@ -282,6 +222,48 @@ module RRSchedule
|
|
282
222
|
dt
|
283
223
|
end
|
284
224
|
|
225
|
+
def update_team_stats(game,cur_gt,cur_ps)
|
226
|
+
@stats[game.team_a][:gt][cur_gt] += 1
|
227
|
+
@stats[game.team_a][:ps][cur_ps] += 1
|
228
|
+
@stats[game.team_b][:gt][cur_gt] += 1
|
229
|
+
@stats[game.team_b][:ps][cur_ps] += 1
|
230
|
+
end
|
231
|
+
|
232
|
+
def get_best_gt(game)
|
233
|
+
x = {}
|
234
|
+
gt_left = @gt_ps_avail.reject{|k,v| v.empty?}
|
235
|
+
gt_left.each_key do |gt|
|
236
|
+
x[gt] = [
|
237
|
+
@stats[game.team_a][:gt][gt] + @stats[game.team_b][:gt][gt],
|
238
|
+
rand(1000)
|
239
|
+
]
|
240
|
+
end
|
241
|
+
x.sort_by{|k,v| [v[0],v[1]]}.first[0]
|
242
|
+
end
|
243
|
+
|
244
|
+
def get_best_ps(game,gt)
|
245
|
+
x = {}
|
246
|
+
@gt_ps_avail[gt].each do |ps|
|
247
|
+
x[ps] = [
|
248
|
+
@stats[game.team_a][:ps][ps] + @stats[game.team_b][:ps][ps],
|
249
|
+
rand(1000)
|
250
|
+
]
|
251
|
+
end
|
252
|
+
x.sort_by{|k,v| [v[0],v[1]]}.first[0]
|
253
|
+
end
|
254
|
+
|
255
|
+
def reset_resource_availability
|
256
|
+
@gt_ps_avail = {}
|
257
|
+
@cur_rule.gt.each do |gt|
|
258
|
+
@gt_ps_avail[gt] = @cur_rule.ps.clone
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def update_resource_availability(cur_gt,cur_ps)
|
263
|
+
@gt_ps_avail[cur_gt].delete(cur_ps)
|
264
|
+
end
|
265
|
+
|
266
|
+
|
285
267
|
#return matchups between two teams
|
286
268
|
def face_to_face(team_a,team_b)
|
287
269
|
res=[]
|
@@ -291,21 +273,20 @@ module RRSchedule
|
|
291
273
|
res.flatten
|
292
274
|
end
|
293
275
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
276
|
+
#Count the number of times each team plays on a given playing surface and at what time. That way
|
277
|
+
#we can balance the available playing surfaces/game times among competitors.
|
278
|
+
def init_stats
|
279
|
+
@stats = {}
|
280
|
+
@teams.flatten.each do |t|
|
281
|
+
@stats[t] = {:gt => {}, :ps => {}}
|
282
|
+
all_gt.each { |gt| @stats[t][:gt][gt] = 0 }
|
283
|
+
all_ps.each { |ps| @stats[t][:ps][ps] = 0 }
|
298
284
|
end
|
299
|
-
gt.flatten.uniq
|
300
285
|
end
|
301
286
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
ps = ps.concat(r.ps)
|
306
|
-
end
|
307
|
-
ps.flatten.uniq
|
308
|
-
end
|
287
|
+
#returns an array of all available game times / playing surfaces, all rules included.
|
288
|
+
def all_gt; @rules.collect{|r| r.gt}.flatten.uniq; end
|
289
|
+
def all_ps; @rules.collect{|r| r.ps}.flatten.uniq; end
|
309
290
|
end
|
310
291
|
|
311
292
|
class Gameday
|
@@ -315,13 +296,11 @@ module RRSchedule
|
|
315
296
|
self.date = params[:date]
|
316
297
|
self.games = params[:games] || []
|
317
298
|
end
|
318
|
-
|
319
299
|
end
|
320
300
|
|
321
301
|
class Rule
|
322
302
|
attr_accessor :wday, :gt, :ps
|
323
303
|
|
324
|
-
|
325
304
|
def initialize(params)
|
326
305
|
self.wday = params[:wday]
|
327
306
|
self.gt = params[:gt]
|
data/test_schedule.rb
CHANGED
@@ -14,3 +14,22 @@ schedule=RRSchedule::Schedule.new(
|
|
14
14
|
:shuffle => true,
|
15
15
|
:start_date => Date.parse("2010/10/13")
|
16
16
|
).generate
|
17
|
+
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'active_support/all'
|
21
|
+
require './lib/rrschedule.rb'
|
22
|
+
include RRSchedule
|
23
|
+
schedule=RRSchedule::Schedule.new(
|
24
|
+
:teams => %w(T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13),
|
25
|
+
:rules => [
|
26
|
+
RRSchedule::Rule.new(
|
27
|
+
:wday => 3,
|
28
|
+
:gt => ["7:00 PM"],
|
29
|
+
:ps => ["1","2","3","4"],
|
30
|
+
)
|
31
|
+
],
|
32
|
+
:cycles => 3,
|
33
|
+
:shuffle => true,
|
34
|
+
:start_date => Date.parse("2010/10/13")
|
35
|
+
).generate
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rrschedule
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.10
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- flamontagne
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-09-
|
13
|
+
date: 2011-09-29 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: thoughtbot-shoulda
|
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
66
|
requirements: []
|
67
67
|
|
68
68
|
rubyforge_project:
|
69
|
-
rubygems_version: 1.8.
|
69
|
+
rubygems_version: 1.8.10
|
70
70
|
signing_key:
|
71
71
|
specification_version: 3
|
72
72
|
summary: Round-Robin schedule generator
|