From 2a8148b8cd52583250518ef8a5f65b33096613bb Mon Sep 17 00:00:00 2001 From: rebuilt Date: Tue, 22 Aug 2023 12:18:18 -0700 Subject: [PATCH] fix: hide scores on analyze page for scores that don't meet the student threshold of 25% --- app/models/survey_item_response.rb | 13 ++-- .../column/gender_column/score_for_gender.rb | 19 +++--- .../graph/column/grade/score_for_grade.rb | 18 ++++- .../column/income_column/score_for_income.rb | 19 +++--- .../analyze/graph/column/score_for_race.rb | 67 ++++++------------- 5 files changed, 61 insertions(+), 75 deletions(-) diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index 50810867..88dd7f1a 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -20,21 +20,22 @@ class SurveyItemResponse < ActiveRecord::Base scope :averages_for_grade, lambda { |survey_items, school, academic_year, grade| SurveyItemResponse.where(survey_item: survey_items, school:, - academic_year:, grade:).group(:survey_item).average(:likert_score) + academic_year:, grade:).group(:survey_item).having("count(*) >= 10").average(:likert_score) } scope :averages_for_gender, lambda { |survey_items, school, academic_year, gender| SurveyItemResponse.where(survey_item: survey_items, school:, - academic_year:, gender:, grade: school.grades(academic_year:)).group(:survey_item).average(:likert_score) + academic_year:, gender:, grade: school.grades(academic_year:)).group(:survey_item).having("count(*) >= 10").average(:likert_score) } scope :averages_for_income, lambda { |survey_items, school, academic_year, income| SurveyItemResponse.where(survey_item: survey_items, school:, - academic_year:, income:, grade: school.grades(academic_year:)).group(:survey_item).average(:likert_score) + academic_year:, income:, grade: school.grades(academic_year:)).group(:survey_item).having("count(*) >= 10").average(:likert_score) } - scope :averages_for_income, lambda { |survey_items, school, academic_year, income| - SurveyItemResponse.where(survey_item: survey_items, school:, - academic_year:, income:).group(:survey_item).average(:likert_score) + scope :averages_for_race, lambda { |school, academic_year, race| + SurveyItemResponse.joins("JOIN student_races on survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where( + school:, academic_year:, grade: school.grades(academic_year:) + ).where("student_races.race_id": race.id).group(:survey_item_id).having("count(*) >= 10").average(:likert_score) } end diff --git a/app/presenters/analyze/graph/column/gender_column/score_for_gender.rb b/app/presenters/analyze/graph/column/gender_column/score_for_gender.rb index 07dfb87c..2b5e22c4 100644 --- a/app/presenters/analyze/graph/column/gender_column/score_for_gender.rb +++ b/app/presenters/analyze/graph/column/gender_column/score_for_gender.rb @@ -5,11 +5,17 @@ module Analyze module ScoreForGender def score(year_index) academic_year = academic_years[year_index] + meets_student_threshold = sufficient_student_responses?(academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + averages = SurveyItemResponse.averages_for_gender(measure.student_survey_items, school, academic_year, gender) average = bubble_up_averages(averages:).round(2) - scorify(average:, meets_student_threshold: sufficient_student_responses?(academic_year:)) + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) end def bubble_up_averages(averages:) @@ -20,16 +26,9 @@ module Analyze end.remove_blanks.average end - def scorify(average:, meets_student_threshold:) - return Score::NIL_SCORE unless meets_student_threshold - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold: true, - meets_admin_data_threshold: false) - end - def sufficient_student_responses?(academic_year:) + return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? + yearly_counts = SurveyItemResponse.where(school:, academic_year:, gender:, survey_item: measure.student_survey_items).group(:gender).select(:response_id).distinct(:response_id).count yearly_counts.any? do |count| diff --git a/app/presenters/analyze/graph/column/grade/score_for_grade.rb b/app/presenters/analyze/graph/column/grade/score_for_grade.rb index 75e28b85..812c9cb9 100644 --- a/app/presenters/analyze/graph/column/grade/score_for_grade.rb +++ b/app/presenters/analyze/graph/column/grade/score_for_grade.rb @@ -4,13 +4,17 @@ module Analyze module Grade module ScoreForGrade def score(year_index) + academic_year = academic_years[year_index] + meets_student_threshold = sufficient_student_responses?(academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + averages = SurveyItemResponse.averages_for_grade(measure.student_survey_items, school, - academic_years[year_index], grade) + academic_year, grade) average = bubble_up_averages(averages:).round(2) Score.new(average:, meets_teacher_threshold: false, - meets_student_threshold: true, + meets_student_threshold:, meets_admin_data_threshold: false) end @@ -21,6 +25,16 @@ module Analyze end.remove_blanks.average end.remove_blanks.average end + + def sufficient_student_responses?(academic_year:) + return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? + + yearly_counts = SurveyItemResponse.where(school:, academic_year:, + survey_item: measure.student_survey_items).group(:grade).select(:response_id).distinct(:response_id).count + yearly_counts.any? do |count| + count[1] >= 10 + end + end end end end diff --git a/app/presenters/analyze/graph/column/income_column/score_for_income.rb b/app/presenters/analyze/graph/column/income_column/score_for_income.rb index 3e1140c3..52a23244 100644 --- a/app/presenters/analyze/graph/column/income_column/score_for_income.rb +++ b/app/presenters/analyze/graph/column/income_column/score_for_income.rb @@ -5,11 +5,17 @@ module Analyze module ScoreForIncome def score(year_index) academic_year = academic_years[year_index] + meets_student_threshold = sufficient_student_responses?(academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + averages = SurveyItemResponse.averages_for_income(measure.student_survey_items, school, academic_year, income) average = bubble_up_averages(averages:).round(2) - scorify(average:, meets_student_threshold: sufficient_student_responses?(academic_year:)) + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) end def bubble_up_averages(averages:) @@ -20,16 +26,9 @@ module Analyze end.remove_blanks.average end - def scorify(average:, meets_student_threshold:) - return Score::NIL_SCORE unless meets_student_threshold - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold: true, - meets_admin_data_threshold: false) - end - def sufficient_student_responses?(academic_year:) + return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? + yearly_counts = SurveyItemResponse.where(school:, academic_year:, income:, survey_item: measure.student_survey_items).group(:income).select(:response_id).distinct(:response_id).count yearly_counts.any? do |count| diff --git a/app/presenters/analyze/graph/column/score_for_race.rb b/app/presenters/analyze/graph/column/score_for_race.rb index 36bee8a5..5fdc2e90 100644 --- a/app/presenters/analyze/graph/column/score_for_race.rb +++ b/app/presenters/analyze/graph/column/score_for_race.rb @@ -3,63 +3,36 @@ module Analyze module Column module ScoreForRace def score(year_index) - academic_year = academic_year_for_year_index(year_index) - rate = response_rate(school:, academic_year:, measure:) - return Score::NIL_SCORE unless rate.meets_student_threshold + academic_year = academic_years[year_index] + meets_student_threshold = sufficient_student_responses?(academic_year:) + return Score::NIL_SCORE unless meets_student_threshold survey_items = measure.student_survey_items - averages = grouped_responses(school:, academic_year:, survey_items:, race:) - meets_student_threshold = sufficient_responses(school:, academic_year:, race:) - scorify(responses: averages, meets_student_threshold:, measure:) - end - - def grouped_responses(school:, academic_year:, survey_items:, race:) - @grouped_responses ||= Hash.new do |memo, (school, academic_year, survey_items, race)| - memo[[school, academic_year, survey_items, race]] = - SurveyItemResponse.joins("JOIN student_races on survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where( - school:, academic_year:, grade: school.grades(academic_year:) - ).where("student_races.race_id": race.id).group(:survey_item_id).having("count(*) >= 10").average(:likert_score) - end - - @grouped_responses[[school, academic_year, survey_items, race]] - end - - def response_rate(school:, academic_year:, measure:) - subcategory = measure.subcategory - @response_rate ||= Hash.new do |memo, (school, academic_year, subcategory)| - memo[[school, academic_year, subcategory]] = subcategory.response_rate(school:, academic_year:) - end - - @response_rate[[school, academic_year, subcategory]] - end + averages = SurveyItemResponse.averages_for_race(school, academic_year, race) + average = bubble_up_averages(averages:).round(2) - def scorify(responses:, meets_student_threshold:, measure:) - averages = bubble_up_averages(responses:, measure:) - average = averages.average.round(2) - - average = 0 unless meets_student_threshold - - Score.new(average:, meets_teacher_threshold: false, meets_student_threshold:, + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, meets_admin_data_threshold: false) end - def sufficient_responses(school:, academic_year:, race:) - @sufficient_responses ||= Hash.new do |memo, (school, academic_year, race)| - number_of_students_for_a_racial_group = SurveyItemResponse.joins("JOIN student_races on survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where( - school:, academic_year: - ).where("student_races.race_id": race.id).distinct.pluck(:student_id).count - memo[[school, academic_year, race]] = number_of_students_for_a_racial_group >= 10 - end - @sufficient_responses[[school, academic_year, race]] - end - - def bubble_up_averages(responses:, measure:) + def bubble_up_averages(averages:) measure.student_scales.map do |scale| scale.survey_items.map do |survey_item| - responses[survey_item.id] + averages[survey_item.id] end.remove_blanks.average - end.remove_blanks + end.remove_blanks.average + end + + def sufficient_student_responses?(academic_year:) + return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? + + number_of_students_for_a_racial_group = SurveyItemResponse.joins("JOIN student_races on survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where( + school:, academic_year: + ).where("student_races.race_id": race.id).distinct.pluck(:student_id).count + number_of_students_for_a_racial_group >= 10 end end end