From 0cb03812cf75e6d2a5055985e054781a07743271 Mon Sep 17 00:00:00 2001 From: Joshua Coles Date: Fri, 6 Oct 2023 22:00:01 +0100 Subject: [PATCH] Track associated toggl entry id for uniqueness, show stats for time spent in different parts of the lecture flow. --- app/jobs/scrape_toggl_job.rb | 66 ++++++++++++++----- app/models/lecture.rb | 24 +++++++ app/views/attendance_tracker/index.html.erb | 65 ++++++++++-------- ...006203421_add_associated_toggl_entry_id.rb | 8 +++ ...3_make_associated_toggl_entry_id_larger.rb | 5 ++ db/schema.rb | 14 +++- 6 files changed, 135 insertions(+), 47 deletions(-) create mode 100644 db/migrate/20231006203421_add_associated_toggl_entry_id.rb create mode 100644 db/migrate/20231006204103_make_associated_toggl_entry_id_larger.rb diff --git a/app/jobs/scrape_toggl_job.rb b/app/jobs/scrape_toggl_job.rb index a9bf326..7faf5ff 100644 --- a/app/jobs/scrape_toggl_job.rb +++ b/app/jobs/scrape_toggl_job.rb @@ -28,30 +28,62 @@ class ScrapeTogglJob < ApplicationJob return if entries_data.empty? - lectures.each do |lecture| - next if lecture.attendance.present? + entries_data.each do |entry| + entry_title = entry['description'] - entries_data.each do |entry| - concurrent_time_entry = entry['time_entries'].find do |inner_entry| + 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 - if concurrent_time_entry.present? - Attendance.create!( - lecture:, - associated_toggl_entry: concurrent_time_entry['id'], + 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 + 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 - ) - elsif entry['description'] == lecture.title - # If the title matches but it wasn't concurrent, then it was a catchup - Attendance.create!( - lecture:, - associated_toggl_entry: entry['time_entries'][0]['id'], - kind: :catchup, - toggl_data: entry + 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)/ + + 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'], + ) + 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'], + ) end end end diff --git a/app/models/lecture.rb b/app/models/lecture.rb index dc0a50d..940e76b 100644 --- a/app/models/lecture.rb +++ b/app/models/lecture.rb @@ -10,6 +10,30 @@ class Lecture < ApplicationRecord :problems_class, ], default: :lecture + def prepared? + tracked_time_entries.where(kind: [:preparation]).any? + end + + def attended? + tracked_time_entries.where(kind: [:concurrent, :catchup]).any? + end + + def reviewed? + tracked_time_entries.where(kind: [:review]).any? + end + + def total_preparation_time + tracked_time_entries.preparation.sum(&:duration).seconds + end + + def total_attendance_time + tracked_time_entries.where(kind: [:concurrent, :catchup]).sum(&:duration).seconds + end + + def total_review_time + tracked_time_entries.review.sum(&:duration).seconds + end + def week_number ((start_time.beginning_of_week - course.semester_start_date.to_time) / 1.week).floor + 1 end diff --git a/app/views/attendance_tracker/index.html.erb b/app/views/attendance_tracker/index.html.erb index 07fbc11..d0b9079 100644 --- a/app/views/attendance_tracker/index.html.erb +++ b/app/views/attendance_tracker/index.html.erb @@ -28,7 +28,7 @@ <% lectures.reject(&:cancelled).each do |lecture| %> <%= lecture.title %> @@ -43,49 +43,56 @@ Cancelled - <% elsif lecture.start_time.future? %> - - - - -
- <%= button_to "Prepare", - lecture_start_preparation_path(id: lecture.id), - class: 'action-button' - %> -
- - - <% else %>
- <% if lecture.attendance.nil? %> - - <% elsif lecture.attendance.kind == 'concurrent' %> - + <% prep_icon_class = if lecture.prepared? + 'text-green-700' + else + 'text-slate-300' + end %> + + <% if lecture.attended? %> - - - <% elsif lecture.attendance.kind == 'catchup' %> - + <% elsif lecture.start_time.past? %> + <% else %> - <% lecture.attendance.kind %> +
<% end %> + + <% reviewed_icon_class = if lecture.start_time.future? + 'invisible' + elsif lecture.reviewed? + 'text-green-700' + else + 'text-slate-300' + end %> +
- <% if lecture.attendance.nil? %> + <% if lecture.start_time.future? %> + <%= button_to "Prepare", + lecture_start_preparation_path(id: lecture.id), + class: 'action-button' + %> + <% elsif lecture.start_time.past? && !lecture.attended? %> <%= button_to "Start", lectures_start_path(id: lecture.id), class: 'action-button' diff --git a/db/migrate/20231006203421_add_associated_toggl_entry_id.rb b/db/migrate/20231006203421_add_associated_toggl_entry_id.rb new file mode 100644 index 0000000..fa9c51b --- /dev/null +++ b/db/migrate/20231006203421_add_associated_toggl_entry_id.rb @@ -0,0 +1,8 @@ +class AddAssociatedTogglEntryId < ActiveRecord::Migration[7.1] + def change + add_column :tracked_time_entries, :associated_toggl_entry_id, :integer, null: false + + # Make column unique + add_index :tracked_time_entries, :associated_toggl_entry_id, unique: true + end +end diff --git a/db/migrate/20231006204103_make_associated_toggl_entry_id_larger.rb b/db/migrate/20231006204103_make_associated_toggl_entry_id_larger.rb new file mode 100644 index 0000000..89806cc --- /dev/null +++ b/db/migrate/20231006204103_make_associated_toggl_entry_id_larger.rb @@ -0,0 +1,5 @@ +class MakeAssociatedTogglEntryIdLarger < ActiveRecord::Migration[7.1] + def change + change_column :tracked_time_entries, :associated_toggl_entry_id, :bigint + end +end diff --git a/db/schema.rb b/db/schema.rb index 1dfc894..3c0a158 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_10_02_152546) do +ActiveRecord::Schema[7.1].define(version: 2023_10_06_204103) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -59,6 +59,18 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_02_152546) do t.index ["recording_uuid"], name: "index_recordings_on_recording_uuid", unique: true end + create_table "tracked_time_entries", force: :cascade do |t| + t.bigint "lecture_id", null: false + t.integer "kind" + t.jsonb "toggl_data" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "associated_toggl_entry_id", null: false + t.index ["associated_toggl_entry_id"], name: "index_tracked_time_entries_on_associated_toggl_entry_id", unique: true + t.index ["lecture_id"], name: "index_tracked_time_entries_on_lecture_id" + end + add_foreign_key "attendances", "lectures" add_foreign_key "recordings", "courses" + add_foreign_key "tracked_time_entries", "lectures" end