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

Standards: teacher_scores query optimizations #33492

Merged
merged 7 commits into from Mar 9, 2020
Merged
50 changes: 24 additions & 26 deletions dashboard/app/models/teacher_score.rb
Expand Up @@ -58,44 +58,42 @@ def self.score_level_for_student(

def self.get_level_scores_for_script_for_section(script_id, section_id)
level_scores_by_student_by_stage_by_script = {}
stage_ids = Script.find(script_id).stages.pluck(:id)
stages = Script.find(script_id).stages
stage_student_level_scores = {}
stage_ids.each do |stage_id|
level_scores = get_level_scores_for_stage_for_section(stage_id, section_id)
stages.each do |stage|
level_scores = get_level_scores_for_stage_for_section(stage, section_id)
unless level_scores.empty?
stage_student_level_scores[stage_id] = level_scores
stage_student_level_scores[stage.id] = level_scores
end
end
level_scores_by_student_by_stage_by_script[script_id] = stage_student_level_scores
level_scores_by_student_by_stage_by_script
end

def self.get_level_scores_for_stage_for_section(stage_id, section_id)
def self.get_level_scores_for_stage_for_section(stage, section_id)
script_id = stage.script_id
student_ids = Section.find(section_id).students.pluck(:id)
student_level_scores = {}
level_ids = stage.script_levels.map(&:level_id)
user_levels = UserLevel.select(:id, :level_id, :user_id).where(user_id: student_ids, level_id: level_ids, script_id: script_id)

teacher_scores = TeacherScore.select(:score, :created_at, :user_level_id).where(
user_level_id: user_levels.pluck(:id)
)

level_scores_by_student = {}
student_ids.each do |student_id|
level_scores = get_level_scores_for_stage_for_student(stage_id, student_id)
unless level_scores.empty?
student_level_scores[student_id] = level_scores
student_user_levels = user_levels.select {|u_l| u_l.user_id == student_id}
student_level_score = {}
student_user_levels.each do |u_l|
teacher_score = teacher_scores.select {|t_s| t_s.user_level_id == u_l.id}.sort_by(&:created_at).last&.score
if teacher_score
student_level_score[u_l.level_id] = teacher_score
end
end
end
student_level_scores
end

def self.get_level_scores_for_stage_for_student(stage_id, student_id)
stage = Stage.find(stage_id)
script_id = stage.script.id
level_ids = stage.script_levels.map(&:level_id)
user_levels = UserLevel.where(user_id: student_id, level_id: level_ids, script_id: script_id)
level_scores = {}
user_levels.each do |user_level|
teacher_score = TeacherScore.where(
user_level_id: user_level.id
)&.order("created_at")&.last&.score
if teacher_score
level_scores[user_level.level_id] = teacher_score
unless student_level_score.empty?
level_scores_by_student[student_id] = student_level_score
end
end
level_scores
level_scores_by_student
end
end
Expand Up @@ -114,6 +114,50 @@ class Api::V1::TeacherScoresControllerTest < ActionDispatch::IntegrationTest
assert_equal formatted_response, "{#{script.id}:{#{stage.id}:{#{student.id}:{#{level.id}:#{score}}}}}"
end

test 'get_teacher_scores_for_script query count' do
teacher = create :teacher
section = create :section, teacher: teacher
10.times do
student = create :student
section.students << student
end
sign_in teacher

script = create :script
script_level = create(
:script_level,
script: script,
levels: [
create(:maze, name: 'test level 1')
]
)
level = script_level.levels[0]
stage = script_level.stage
score = 100

section.students.each do |student|
create :user_level, user: student, level: level, script: script
end

post '/dashboardapi/v1/teacher_scores', params: {section_id: section.id, stage_scores: [{stage_id: stage.id, score: score}]}

assert_queries 11 do
get "/dashboardapi/v1/teacher_scores/#{section.id}/#{script.id}"
end

assert_equal section.students.count, 10

student = create :student
section.students << student
create :user_level, user: student, level: level, script: script

assert_equal section.students.count, 11

assert_queries 11 do
get "/dashboardapi/v1/teacher_scores/#{section.id}/#{script.id}"
end
end

private

def formatted_response
Expand Down
14 changes: 3 additions & 11 deletions dashboard/test/models/teacher_score_test.rb
Expand Up @@ -93,15 +93,7 @@ class TeacherScoreTest < ActiveSupport::TestCase
assert_equal(teacher_scores_count_after, teacher_scores_count_before + student_count)
end

test 'get scores for stage for student' do
TeacherScore.score_level_for_student(
@teacher.id, @student_1.id, @level_1.id, @script.id, @score
)

assert_equal(TeacherScore.get_level_scores_for_stage_for_student(@stage.id, @student_1.id), {@level_1.id => @score})
end

test 'get scores for stage for student looks at most recent score' do
test 'get scores for stage looks at most recent score' do
Timecop.freeze do
TeacherScore.score_level_for_student(
@teacher.id, @student_1.id, @level_1.id, @script.id, @score
Expand All @@ -114,7 +106,7 @@ class TeacherScoreTest < ActiveSupport::TestCase
)
end

assert_equal(TeacherScore.get_level_scores_for_stage_for_student(@stage.id, @student_1.id), {@level_1.id => @score_2})
assert_equal(TeacherScore.get_level_scores_for_stage_for_section(@stage, @section.id), {@student_1.id => {@level_1.id => @score_2}})
end

test 'get scores for stage for section' do
Expand All @@ -124,7 +116,7 @@ class TeacherScoreTest < ActiveSupport::TestCase

assert_equal(
TeacherScore.get_level_scores_for_stage_for_section(
@stage.id,
@stage,
@section.id
),
{
Expand Down