lecture-attendance-manager/app/models/course.rb

100 lines
3.3 KiB
Ruby

class Course < ApplicationRecord
has_many :lectures, -> { order("start_time") }, dependent: :destroy
has_many :work_items, dependent: :destroy
# A course has a standalone connection to its recordings. To be displayed they must be associated with a lecture but
# we them independently to avoid re-importing lectures.
has_many :recordings, dependent: :destroy
scope :active, -> { where(archived: false) }
def lectures_and_work_items
(lectures + work_items).sort_by(&:start_time)
end
def import_from_calendar!
ics_file = HTTParty.get("https://mytimetable.bath.ac.uk/ical?6519757b&group=false&timetable=!MjAyMyFzdHVkZW50c2V0ITRDRjQ5MjlGRTg1M0Q4N0MyMDZENTVDNUQ3QTJFNzk0&eu=amMzMDkxQGJhdGguYWMudWs=&h=MiuDbRiudE_Yf7B25v2SfEuFCtmYGkFb5sAUI3yGmtY=")
calendars = Icalendar::Calendar.parse(ics_file)
calendar = calendars.first
events = calendar.events.map do |event|
# Example title include: PH40065B-Lab, PH40112-Lecc (Wk 19-25, 29-32), MA40049-Leca (LOIL), MA40049-Lecb
summary = event.summary
match = /(^\w\w\d{5})-(\w+)/.match(summary)
# Handle odd events we don't care about
next if match.nil?
unit_code = match[1]
short_lecture_title = match[2]
start_time = event.dtstart.to_time
event_uuid = event.uid.to_s
next if unit_code.nil? ||
short_lecture_title.nil? ||
event_uuid.nil? ||
start_time.nil? ||
unit_code != self.unit_code
{
unit_code:,
short_lecture_title:,
start_time:,
event_uuid:,
online: summary.include?("LOIL"),
}
end
lecture_counter = 0
events.compact.each do |event|
# Naive check to see if we've already created this lecture
if lectures.find_by(event_uuid: event[:event_uuid]).present? || lectures.find_by(
start_time: (event[:start_time].beginning_of_hour + 5.minutes)..(event[:start_time].beginning_of_hour + 1.hour + 5.minutes)
).present?
next
end
if event[:short_lecture_title].starts_with? "Lec"
lecture_counter += 1
title = "Lecture #{lecture_counter}"
else
title = event[:short_lecture_title]
end
lectures.create!(
title: title,
start_time: event[:start_time],
event_uuid: event[:event_uuid],
online: event[:online],
live_video_url: if event[:online]
self.default_live_video_url
else
nil
end,
)
end
end
# What should this do for existing attendances?
def renumber_lectures!
lectures.group_by(&:kind).each do |kind, lectures|
lectures.sort_by(&:start_time).each_with_index do |lecture, index|
lecture.update!(title: "#{kind.to_s.humanize} #{index + 1}")
end
end
end
def fill_in_default_live_video_url!
raise "No default live video URL set" if self.default_live_video_url.nil?
lectures.where(live_video_url: nil).update_all(live_video_url: self.default_live_video_url)
end
# Sometimes our toggl entries get mismatched or otherwise out of sync. This method will delete all tracked time entries
# for this course and then re-import them from Toggl.
def redo_toggl_entries!
TrackedTimeEntry.where(lecture: lectures).destroy_all
ScrapeTogglJob.perform_later([self.id])
end
end