Skip to content

Commit

Permalink
refactor(reference time): extract end_at from SQL
Browse files Browse the repository at this point in the history
for performance efficiency while getting statistics
  • Loading branch information
bivanalhar committed Feb 7, 2024
1 parent beec25a commit d506041
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true
module Course::Statistics::ReferenceTimesConcern
private

def personal_end_at_hash
personal_end_at = Course::PersonalTime.find_by_sql(<<-SQL.squish
WITH course_user_personal_end_at AS (
SELECT course_user_id, end_at
FROM course_personal_times cpt
JOIN (
SELECT course_lesson_plan_items.id
FROM course_lesson_plan_items
WHERE course_lesson_plan_items.actable_type = 'Course::Assessment'
AND course_lesson_plan_items.actable_id = #{assessment_params[:id]}
) clpi
ON cpt.lesson_plan_item_id = clpi.id
),
personal_times AS (
SELECT cu.id AS course_user_id, pt.end_at
FROM (
SELECT course_users.id
FROM course_users
WHERE course_users.course_id = #{@assessment.course.id}
) cu
LEFT JOIN (
SELECT course_user_id, end_at
FROM course_user_personal_end_at
) pt
ON cu.id = pt.course_user_id
),
personal_reference_times AS (
SELECT cu.id AS course_user_id, crt.end_at
FROM (
SELECT course_users.id, course_users.reference_timeline_id
FROM course_users
WHERE course_users.course_id = #{@assessment.course.id} AND course_users.role = #{CourseUser.roles[:student]}
) cu
LEFT JOIN (
SELECT reference_timeline_id, lesson_plan_item_id, end_at
FROM course_reference_times
) crt
ON crt.reference_timeline_id = cu.reference_timeline_id
LEFT JOIN (
SELECT id
FROM course_lesson_plan_items
WHERE course_lesson_plan_items.actable_type = 'Course::Assessment'
AND course_lesson_plan_items.actable_id = #{assessment_params[:id]}
) clpi
ON crt.lesson_plan_item_id = clpi.id
)
SELECT
pt.course_user_id,
CASE WHEN pt.end_at IS NOT NULL THEN pt.end_at ELSE prt.end_at END AS end_at
FROM personal_times pt
LEFT JOIN personal_reference_times prt
ON pt.course_user_id = prt.course_user_id
SQL
)
personal_end_at.map { |pea| [pea.course_user_id, pea.end_at] }.to_h
end

def reference_times_hash
reference_times = Course::ReferenceTime.find_by_sql(<<-SQL.squish
SELECT clpi.actable_id AS lesson_plan_item_id, crt.end_at
FROM course_reference_times crt
JOIN (
SELECT id
FROM course_reference_timelines
WHERE course_id = #{@assessment.course.id} AND "default" = TRUE
) crtl
ON crt.reference_timeline_id = crtl.id
JOIN (
SELECT id, actable_id
FROM course_lesson_plan_items
WHERE course_lesson_plan_items.actable_type = 'Course::Assessment'
AND course_lesson_plan_items.actable_id = #{assessment_params[:id]}
) clpi
ON crt.lesson_plan_item_id = clpi.id
SQL
)
reference_times.map { |rt| [rt.lesson_plan_item_id, rt.end_at] }.to_h
end
end
14 changes: 12 additions & 2 deletions app/controllers/concerns/course/statistics/submissions_concern.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true
module Course::Statistics::SubmissionsConcern
include Course::Statistics::ReferenceTimesConcern

private

def initialize_student_hash(students)
Expand Down Expand Up @@ -80,26 +82,34 @@ def answer_statistics_hash

def populate_hash_including_answers(student_hash, submissions)
answers_hash = answer_statistics_hash
fetch_personal_and_reference_timeline_hash

submissions.map do |submission|
submitter_course_user = submission.creator.course_users.select { |u| u.course_id == @assessment.course_id }.first
next unless submitter_course_user&.student?

answers = answers_hash[submission.id]
end_at = @assessment.lesson_plan_item.time_for(submitter_course_user).end_at
end_at = @personal_end_at_hash[submitter_course_user.id] || @reference_times_hash[@assessment.id]

student_hash[submitter_course_user] = [submission, answers, end_at]
end
end

def populate_hash_without_answers(student_hash, submissions)
fetch_personal_and_reference_timeline_hash

submissions.map do |submission|
submitter_course_user = submission.creator.course_users.select { |u| u.course_id == @assessment.course_id }.first
next unless submitter_course_user&.student?

end_at = @assessment.lesson_plan_item.time_for(submitter_course_user).end_at
end_at = @personal_end_at_hash[submitter_course_user.id] || @reference_times_hash[@assessment.id]

student_hash[submitter_course_user] = [submission, end_at]
end
end

def fetch_personal_and_reference_timeline_hash
@personal_end_at_hash = personal_end_at_hash
@reference_times_hash = reference_times_hash
end
end
3 changes: 1 addition & 2 deletions app/controllers/course/statistics/assessments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ class Course::Statistics::AssessmentsController < Course::Statistics::Controller
def main_statistics
@assessment = Course::Assessment.where(id: assessment_params[:id]).
calculated(:maximum_grade, :question_count).
preload(lesson_plan_item: [:reference_times, personal_times: :course_user],
course: :course_users).first
preload(course: :course_users).first
submissions = Course::Assessment::Submission.where(assessment_id: assessment_params[:id]).
calculated(:grade, :grader_ids).
preload(creator: :course_users)
Expand Down

0 comments on commit d506041

Please sign in to comment.