All checks were successful
Build and Publish Docker Container / build (push) Successful in 5m29s
This update enhances tracking functionality. It adds the ability to track time spent 'catching up' on lectures, with distinctions made within the controllers and views to handle these new 'catch-up' entries. Also implemented a flexible match for lecture titles to include various forms such as 'Lecture 1', 'Lecture 1: Prep' and the 'Catch-up'.
113 lines
3.6 KiB
Ruby
113 lines
3.6 KiB
Ruby
class ScrapeTogglJob < ApplicationJob
|
|
queue_as :default
|
|
|
|
def perform(course_ids)
|
|
courses = Course.where(id: course_ids)
|
|
|
|
courses.each do |course|
|
|
self.scrape_course(course)
|
|
end
|
|
end
|
|
|
|
# @param [Course] course
|
|
def scrape_course(course)
|
|
toggl_project_id = course.toggl_project
|
|
lectures = course.lectures.order(:start_time).includes(:tracked_time_entries)
|
|
|
|
return if lectures.empty?
|
|
|
|
entries_data = Toggl::entries_for_project(
|
|
toggl_project_id,
|
|
|
|
# TODO: Work out better limits
|
|
start_time: course.semester_start_date - 2.months,
|
|
end_time: course.semester_start_date + 15.weeks + 2.months,
|
|
)
|
|
|
|
puts("Entries data for #{course.title}: #{entries_data}")
|
|
|
|
return if entries_data.empty?
|
|
|
|
entries_data.each do |entry|
|
|
entry_title = entry['description']
|
|
|
|
# Skip if we've already seen this entry, NOTE: we assume that there is only one inner_entry per time entry
|
|
next if TrackedTimeEntry.exists?(associated_toggl_entry_id: entry['time_entries'][0]['id'])
|
|
|
|
if (lecture = lectures.find_by(title: entry_title))
|
|
is_concurrent = entry['time_entries'].any? do |inner_entry|
|
|
(Time.new(inner_entry['start']) - lecture.start_time).abs < 10.minutes
|
|
end
|
|
|
|
kind = if is_concurrent
|
|
:concurrent
|
|
else
|
|
:catchup
|
|
end
|
|
|
|
lecture.tracked_time_entries.create!(
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
|
|
# TODO: What should happen if the time entry is materially before the lecture?
|
|
kind:
|
|
) and next
|
|
elsif (work_item = course.work_items.find_by(title: entry_title))
|
|
work_item.tracked_time_entries.create!(
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
kind: :generic
|
|
) and next
|
|
end
|
|
|
|
concurrent_unlabeled = entry['time_entries'].any? do |inner_entry|
|
|
lecture = lectures.find do |lecture|
|
|
(Time.new(inner_entry['start']) - lecture.start_time).abs < 10.minutes
|
|
end
|
|
|
|
if lecture.present?
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :concurrent,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: inner_entry['id']
|
|
)
|
|
end
|
|
|
|
lecture.present?
|
|
end
|
|
|
|
next if concurrent_unlabeled
|
|
|
|
preparation_regex = /^(.+): ?(?:Prep|Preparation)?$/
|
|
review_regex = /^(.+): ?(?:Review|Recap)/
|
|
catchup_regex = /^(.+): ?(?:Catch-up|Catch up|Catch Up)/
|
|
|
|
if (lecture_title_match = entry_title.match(preparation_regex)) and (lecture = lectures.find_by(title: lecture_title_match[1]))
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :preparation,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
)
|
|
|
|
# broadcast_update_to lecture, :lectures
|
|
elsif (lecture_title_match = entry_title.match(review_regex)) and (lecture = lectures.find_by(title: lecture_title_match[1]))
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :review,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
)
|
|
|
|
# broadcast_update_to lecture, :lectures
|
|
elsif (lecture_title_match = entry_title.match(catchup_regex)) and (lecture = lectures.find_by(title: lecture_title_match[1]))
|
|
lecture.tracked_time_entries.create!(
|
|
kind: :catchup,
|
|
toggl_data: entry,
|
|
associated_toggl_entry_id: entry['time_entries'][0]['id'],
|
|
)
|
|
|
|
# broadcast_update_to lecture, :lectures
|
|
end
|
|
end
|
|
end
|
|
end
|