lecture-attendance-manager/app/jobs/scrape_toggl_job.rb
Joshua Coles 4b3204d2f4
All checks were successful
Build and Publish Docker Container / build (push) Successful in 5m29s
Implement catch-up tracking feature
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'.
2024-02-07 10:46:47 +00:00

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