Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: Correct student list query to ensure all students appear #302

Merged
merged 2 commits into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,11 @@ def convert_hash_to_pct(hash, total)
# Total task counts must contain an array of the cummulative task counts (with none being 0)
# Project task counts is an object with fail_count, complete_count etc for each status
def self.create_task_stats_from(total_task_counts, project_task_counts, target_grade)

TaskStatus.all.each do |s|
project_task_counts["#{s.status_key}_count"] = 0 if project_task_counts["#{s.status_key}_count"].nil?
end

red_pct = ((project_task_counts.fail_count + project_task_counts.do_not_resubmit_count + project_task_counts.time_exceeded_count) / total_task_counts[target_grade]).signif(2)
orange_pct = ((project_task_counts.redo_count + project_task_counts.need_help_count + project_task_counts.fix_and_resubmit_count) / total_task_counts[target_grade]).signif(2)
green_pct = ((project_task_counts.discuss_count + project_task_counts.demonstrate_count + project_task_counts.complete_count) / total_task_counts[target_grade]).signif(2)
Expand Down
22 changes: 17 additions & 5 deletions app/models/unit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,19 @@ def student_query(limit_to_enrolled)
task_definitions.where("target_grade <= #{e}").count + 0.0
end.map { |e| e == 0 ? 1 : e }

# Get the task stats for a student as a subquery so that it is independent of the main query
# otherwise an attempt at a higher level task can exclude the student from the student list!
subquery = projects.
joins(tasks: :task_definition).
where(
'projects.target_grade >= task_definitions.target_grade'
).
group('projects.id').
select(
"projects.id AS project_id",
*TaskStatus.all.map { |s| "SUM(CASE WHEN tasks.task_status_id = #{s.id} THEN 1 ELSE 0 END) AS #{s.status_key}_count" },
).to_sql

q = projects
.joins(:user)
.joins('LEFT OUTER JOIN tasks ON projects.id = tasks.project_id')
Expand All @@ -323,6 +336,7 @@ def student_query(limit_to_enrolled)
.joins('LEFT OUTER JOIN tutorial_enrolments ON tutorial_enrolments.project_id = projects.id')
.joins('LEFT OUTER JOIN tutorials ON tutorials.id = tutorial_enrolments.tutorial_id')
.joins('LEFT OUTER JOIN tutorial_streams ON tutorials.tutorial_stream_id = tutorial_streams.id')
.joins("LEFT OUTER JOIN (#{subquery}) as sq ON sq.project_id = projects.id")
.group(
'projects.id',
'projects.target_grade',
Expand All @@ -336,7 +350,8 @@ def student_query(limit_to_enrolled)
'projects.portfolio_production_date',
'projects.compile_portfolio',
'projects.grade',
'projects.grade_rationale'
'projects.grade_rationale',
*TaskStatus.all.map { |s| "#{s.status_key}_count" },
)
.select(
'projects.id AS project_id',
Expand All @@ -353,15 +368,12 @@ def student_query(limit_to_enrolled)
'projects.grade_rationale AS grade_rationale',
'projects.portfolio_production_date AS portfolio_production_date',
'MAX(CASE WHEN plagiarism_match_links.dismissed = FALSE THEN plagiarism_match_links.pct ELSE 0 END) AS plagiarism_match_links_max_pct',
*TaskStatus.all.map { |s| "SUM(CASE WHEN tasks.task_status_id = #{s.id} THEN 1 ELSE 0 END) AS #{s.status_key}_count" },
*TaskStatus.all.map { |s| "sq.#{s.status_key}_count AS #{s.status_key}_count" },
# Get tutorial for each stream in unit
*tutorial_streams.map { |s| "MAX(CASE WHEN tutorials.tutorial_stream_id = #{s.id} OR tutorials.tutorial_stream_id IS NULL THEN tutorials.id ELSE NULL END) AS tutorial_#{s.id}" },
# Get tutorial for case when no stream
"MAX(CASE WHEN tutorial_streams.id IS NULL THEN tutorials.id ELSE NULL END) AS tutorial"
)
.where(
'projects.target_grade >= task_definitions.target_grade OR (task_definitions.target_grade IS NULL)'
)
.order('users.first_name')

q = q.where('projects.enrolled = TRUE') if limit_to_enrolled
Expand Down