Subversion Repositories mildred

Rev

Blame | Compare with Previous | Last modification | View Log | RSS feed

class Schedule

  cattr_accessor :logger

  QBeat.setup_logging

  # returns a programming block representing the current date/time in the
  # schedule
  #
  # Time should only be set for testing purposes
  def self.load(filename, time=Time.now)
    sched = load_schedule_file(filename)
    today = sched.find_all {|slot| slot.is_today?(time)}
    today.each do |slot|
      return load_pblock(filename, slot) if slot.is_now?(time)
    end

    today << time
    today.sort!

    today.each_index do |idx|
      slot = today[idx]
      if slot.kind_of?(Time)
        if slot == today.first
          ts = TimeSlot.new(:start => 0, :end => today[idx+1].start)
        elsif slot == today.last
          ts = TimeSlot.new(:start => today[idx-1].end, :end => 0)
        else
          ts = TimeSlot.new(:start => today[idx-1].end,
                            :end => today[idx+1].start)
        end
        return ProgrammingBlock.default(:name => "Random",
                                        :description => "Pure random",
                                        :time_slot => ts)
      end
    end
    raise "I screwed up!"
  end

  # Take a schedule file, and return an array of sorted TimeSlot objects
  def self.load_schedule_file(filename)
    begin
      sched = YAML::load_file(filename)
      sched.map! {|slot| TimeSlot.new(slot)}
      sched.sort
    rescue Exception => ex
      logger.error("Failed to load schedule: #{ex.inspect}")
      logger.warn("Loading default programming block")
      [TimeSlot.default]
    end
  end

  def self.load_pblock(filename, time_slot)
    begin
      return ProgrammingBlock.default unless time_slot.pblock
      filename = File.join(PB_DIR, time_slot.pblock + ".yml")
      return ProgrammingBlock.default unless File.exist?(filename)

      yaml_pb = YAML::load_file(filename).symbolize_keys
      yaml_pb[:filename] = filename
      yaml_pb[:time_slot] = time_slot
      ProgrammingBlock.new(yaml_pb)
    rescue Exception => ex
      logger.error("#{ex.inspect}\n+#{ex.backtrace.join("\n")}")
      ProgrammingBlock.default
    end
  end

  def initialize
    @@logger = nil
  end

  # Iterate through the day's programming blocks, returning an array of them.
  def self.for(filename, date=Time.now)
    sched = load_schedule_file(filename)
    pblocks = []
    today = sched.find_all {|slot| slot.is_today?(date)}.sort
    date = date.midnight
    tomorrow = date.tomorrow

    loop do
      pblocks << pblock = load(filename, date)
      date = TimeSlot.blend_with(pblock.end, date)
      break if date >= tomorrow || pblock.end == "00:00"
    end
    pblocks
  end

  def self.for_week_of(filename, date=Time.now)
    days = []
    sched = load_schedule_file(filename)
    orig_date = date
   
    0.upto(6) do |x|
      pblocks = []
      today = sched.find_all {|slot| slot.is_today?(orig_date + x.days)}.sort
      date = (orig_date + x.days).midnight
      tomorrow = date.tomorrow
      loop do
        pblocks << pblock = load(filename, date)
        date = TimeSlot.blend_with(pblock.end, date)
        break if date >= tomorrow || pblock.end == "00:00"
      end
      days << pblocks
    end
    days
  end
 
  def self.matches?(filename, pblock, time=Time.now)
    now_pblock = load(filename, time)
    now_pblock == pblock
  end

  private

  # TODO this is kinda crappy
  if RAILS_ENV == "test"
    PB_DIR = File.join(RAILS_ROOT, "spec", "fixtures", "programming_blocks")
  else
    PB_DIR = File.join(RAILS_ROOT, "config", "programming_blocks")
  end

  def self.to_hour_min(time)
    begin
      raise "foo" if /^(\d{1,2})(?::(\d{2}))?$/.match(time.to_s).nil?
      hour = $~[1].to_i % 24
      min = $~[2].to_i
      sprintf("%02d:%02d", hour, min)
    rescue Exception
      raise "Invalid schedule time format: '#{time}'"
    end
  end
end