lib/rrschedule.rb in rrschedule-0.1.4 vs lib/rrschedule.rb in rrschedule-0.1.5
- old
+ new
@@ -3,27 +3,28 @@
############################################################################################################################
require 'active_support'
module RRSchedule
class Schedule
attr_accessor :playing_surfaces, :game_times, :cycles, :wdays, :start_date, :exclude_dates, :shuffle_initial_order
- attr_reader :teams, :rounds
+ attr_reader :teams, :rounds, :gamedays
def initialize(params={})
+ @gamedays = []
self.teams = params[:teams] || [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
self.playing_surfaces = Array(params[:playing_surfaces]).empty? ? ["Surface A", "Surface B"] : Array(params[:playing_surfaces])
self.cycles = params[:cycles] || 1
self.game_times = Array(params[:game_times]).empty? ? ["7:00 PM", "9:00 PM"] : Array(params[:game_times])
- self.game_times.collect! do |gt|
+ self.game_times.collect! do |gt|
begin
DateTime.parse(gt)
rescue
raise "game times must be valid time representations in the string form (e.g. 3:00 PM, 11:00 AM, 18:20, etc)"
end
end
- self.shuffle_initial_order = params[:shuffle_initial_order] || true
+ self.shuffle_initial_order = params[:shuffle_initial_order].nil? ? true : params[:shuffle_initial_order]
self.exclude_dates = params[:exclude_dates] || []
self.start_date = params[:start_date] || Time.now.beginning_of_day
self.wdays = Array(params[:wdays]).empty? ? [1] : Array(params[:wdays])
raise "each value in wdays must be between 0 and 6" if self.wdays.reject{|w| (0..6).member?(w)}.size > 0
@@ -81,45 +82,41 @@
end
def face_to_face(team_a,team_b)
res=[]
- self.gamedays.each do |gd,games|
- res << games.select {|g| (g.team_a == team_a && g.team_b == team_b) || (g.team_a == team_b && g.team_b == team_a)}
+ self.gamedays.each do |gd|
+ res << gd.games.select {|g| (g.team_a == team_a && g.team_b == team_b) || (g.team_a == team_b && g.team_b == team_a)}
end
res.flatten
end
def to_s
res = ""
- res << "#{@schedule.keys.size.to_s} gamedays\n"
- @schedule.sort.each do |gd,games|
- res << gd.strftime("%Y-%m-%d") + "\n"
+ res << "#{self.gamedays.size.to_s} gamedays\n"
+ self.gamedays.each do |gd|
+ res << gd.date.strftime("%Y-%m-%d") + "\n"
res << "==========\n"
- games.each do |g|
+ gd.games.each do |g|
res << "#{g.team_a.to_s} VS #{g.team_b.to_s} on playing surface #{g.playing_surface} at #{g.game_time.strftime("%I:%M %p")}\n"
end
res << "\n"
end
res
end
-
- def gamedays
- @schedule.sort
- end
-
- def by_team(team)
+
+ #TODO: should return either a Schedule instance or a TeamSchedule instance (this class doesn't exist yet)
+ def by_team(team)
gms=[]
- self.gamedays.each do |gd,games|
- gms << games.select{|g| g.team_a == team || g.team_b == team}
+ self.gamedays.each do |gd|
+ gms << gd.games.select{|g| g.team_a == team || g.team_b == team}
end
gms.flatten
end
- #TODO: returns true if the generated schedule is a valid round-robin (for testing purpose)
- def round_robin?
-
+ #returns true if the generated schedule is a valid round-robin (for testing purpose)
+ def round_robin?
#each round-robin round should contains n-1 games where n is the nbr of teams (:dummy included if odd)
return false if self.rounds.size != (@teams.size*self.cycles)-self.cycles
#check if each team plays the same number of games against each other
self.teams.each do |t1|
@@ -128,52 +125,52 @@
end
end
return true
end
- private
-
def teams=(arr)
@teams = arr.clone
raise ":dummy is a reserved team name. Please use something else" if @teams.member?(:dummy)
raise "at least 2 teams are required" if @teams.size == 1
@teams << :dummy if @teams.size.odd?
end
-
- #Let's slice our games according to our physical constraints
+
+ private
+ #Slice games according to playing surfaces and game times
def slice(games)
- res={}
slices = games.each_slice(games_per_day)
wdays_stack = self.wdays.clone
cur_date = self.start_date
slices.each_with_index do |slice,i|
- gt_stack = self.game_times.clone
- ps_stack = self.playing_surfaces.clone
+ gt_stack = self.game_times.clone.sort_by{rand}
+ ps_stack = self.playing_surfaces.clone.sort_by{rand}
wdays_stack = self.wdays.clone if wdays_stack.empty?
cur_wday = wdays_stack.shift
cur_date = next_game_date(cur_date,cur_wday)
cur_gt = gt_stack.shift
- res[cur_date] = []
+ gameday = Gameday.new(:date => cur_date)
+
slice.each_with_index do |g,game_index|
cur_ps = ps_stack.shift
- res[cur_date] << Game.new(
+ gameday.games << Game.new(
:team_a => g[:team_a],
:team_b => g[:team_b],
:playing_surface => cur_ps,
:game_time => cur_gt,
:game_date => cur_date)
+
cur_gt = gt_stack.shift if ps_stack.empty?
gt_stack = self.game_times.clone if gt_stack.empty?
ps_stack = self.playing_surfaces.clone if ps_stack.empty?
end
- res[cur_date] = res[cur_date].sort_by {|g| [g.game_time,g.playing_surface]}
+ gameday.games = gameday.games.sort_by {|g| [g.game_time,g.playing_surface]}
+ self.gamedays << gameday
cur_date += 1.day
end
- @schedule = res
end
def next_game_date(dt,wday)
dt += 1.days until wday == dt.wday && !self.exclude_dates.include?(dt)
dt
@@ -181,11 +178,21 @@
def games_per_day
self.playing_surfaces.size * self.game_times.size
end
end
-
+
+ class Gameday
+ attr_accessor :date, :games
+
+ def initialize(params)
+ self.date = params[:date]
+ self.games = params[:games] || []
+ end
+
+ end
+
class Game
attr_accessor :team_a, :team_b, :playing_surface, :game_time, :game_date
def initialize(params={})
self.team_a = params[:team_a]
@@ -199,10 +206,10 @@
class Round
attr_accessor :round, :games
def initialize(params={})
self.round = params[:round]
- self.games = params[:games]
+ self.games = params[:games] || []
end
end
end