diff --git a/app/controllers/overview_controller.rb b/app/controllers/overview_controller.rb index bedf6094..9e15112a 100644 --- a/app/controllers/overview_controller.rb +++ b/app/controllers/overview_controller.rb @@ -16,13 +16,17 @@ class OverviewController < SqmApplicationController end def check_empty_dataset - @has_empty_dataset = measures.all? do |measure| - measure.none_meet_threshold? school: @school, academic_year: @academic_year + @has_empty_dataset = subcategories.all? do |subcategory| + response_rate = subcategory.response_rate(school: @school, academic_year: @academic_year) + !response_rate.meets_student_threshold && !response_rate.meets_teacher_threshold end end def measures - @measures ||= Measure.all.includes(%i[scales admin_data_items subcategory - category]).includes(subcategory: :measures) + @measures ||= Measure.all.includes(%i[scales admin_data_items category]) + end + + def subcategories + @subcategories ||= Subcategory.all end end diff --git a/app/helpers/analyze_helper.rb b/app/helpers/analyze_helper.rb index af340f54..3bfaa39d 100644 --- a/app/helpers/analyze_helper.rb +++ b/app/helpers/analyze_helper.rb @@ -74,7 +74,8 @@ module AnalyzeHelper def empty_dataset?(measures:, school:, academic_year:) @empty_dataset ||= Hash.new do |memo, (school, academic_year)| memo[[school, academic_year]] = measures.all? do |measure| - measure.survey_item_responses.where(school:, academic_year:).none? || measure.none_meet_threshold?(school:, academic_year:) + response_rate = measure.subcategory.response_rate(school:, academic_year:) + !response_rate.meets_student_threshold && !response_rate.meets_teacher_threshold end end diff --git a/app/models/measure.rb b/app/models/measure.rb index 882c0d69..e05c6684 100644 --- a/app/models/measure.rb +++ b/app/models/measure.rb @@ -202,35 +202,15 @@ class Measure < ActiveRecord::Base averages.average end - def student_survey_items_have_no_responses?(school:, academic_year:) - @student_survey_items_have_no_responses ||= Hash.new do |memo, (school, academic_year)| - memo[[school, academic_year]] = student_scales.all? do |scale| - scale.survey_item_responses.where(school:, academic_year:).none? - end - end - @student_survey_items_have_no_responses[[school, academic_year]] - end - - def teacher_survey_items_have_no_responses?(school:, academic_year:) - @teacher_survey_items_have_no_responses ||= Hash.new do |memo, (school, academic_year)| - memo[[school, academic_year]] = teacher_scales.all? do |scale| - scale.survey_item_responses.where(school:, academic_year:).none? - end - end - @teacher_survey_items_have_no_responses[[school, academic_year]] - end - def sufficient_student_data?(school:, academic_year:) return false unless includes_student_survey_items? - return false if student_survey_items_have_no_responses?(school:, academic_year:) - @sufficient_student_data ||= subcategory.student_response_rate(school:, academic_year:).meets_student_threshold? + @sufficient_student_data ||= subcategory.response_rate(school:, academic_year:).meets_student_threshold end def sufficient_teacher_data?(school:, academic_year:) return false unless includes_teacher_survey_items? - return false if teacher_survey_items_have_no_responses?(school:, academic_year:) - @sufficient_teacher_data ||= subcategory.teacher_response_rate(school:, academic_year:).meets_teacher_threshold? + @sufficient_teacher_data ||= subcategory.response_rate(school:, academic_year:).meets_teacher_threshold end end diff --git a/app/models/response_rate_calculator.rb b/app/models/response_rate_calculator.rb index 48b3b6b3..41ca22fb 100644 --- a/app/models/response_rate_calculator.rb +++ b/app/models/response_rate_calculator.rb @@ -1,6 +1,7 @@ module ResponseRateCalculator TEACHER_RATE_THRESHOLD = 25 STUDENT_RATE_THRESHOLD = 25 + attr_reader :subcategory, :school, :academic_year def initialize(subcategory:, school:, academic_year:) @subcategory = subcategory @@ -29,6 +30,8 @@ module ResponseRateCalculator rate >= TEACHER_RATE_THRESHOLD end + private + def cap_at_100(response_rate) response_rate > 100 ? 100 : response_rate end diff --git a/app/models/student_response_rate_calculator.rb b/app/models/student_response_rate_calculator.rb index 47713b2a..daab4f01 100644 --- a/app/models/student_response_rate_calculator.rb +++ b/app/models/student_response_rate_calculator.rb @@ -5,12 +5,13 @@ class StudentResponseRateCalculator def survey_item_count @survey_item_count ||= begin - survey = Survey.where(school: @school, academic_year: @academic_year).first + survey = Survey.find_by(school:, academic_year:) + survey_items = SurveyItem.includes(%i[scale measure]).student_survey_items.where("scale.measure": @subcategory.measures) survey_items = survey_items.where(on_short_form: true) if survey.form == 'short' survey_items = survey_items.reject do |survey_item| - survey_item.survey_item_responses.where(school: @school, academic_year: @academic_year).none? + survey_item.survey_item_responses.where(school:, academic_year:).none? end survey_items.count end @@ -19,40 +20,21 @@ class StudentResponseRateCalculator def response_count @response_count ||= @subcategory.measures.map do |measure| measure.student_survey_items.map do |survey_item| - survey_item.survey_item_responses.where(school: @school, - academic_year: @academic_year).exclude_boston.count + survey = Survey.find_by(school:, academic_year:) + next 0 if survey.form == 'short' && survey_item.on_short_form == false + + survey_item.survey_item_responses.where(school:, + academic_year:).exclude_boston.count end.sum end.sum end def total_possible_responses @total_possible_responses ||= begin - total_responses = Respondent.where(school: @school, academic_year: @academic_year).first + total_responses = Respondent.find_by(school:, academic_year:) return 0 unless total_responses.present? total_responses.total_students end end end - -# survey = Survey.where(school:, academic_year:).first -# total_possible_student_responses = Respondent.where(school:, academic_year:).first - -# student_survey_items = Subcategory.all.map do |subcategory| -# subcategory.measures.map do |measure| -# measure.student_scales.map do |scale| -# scale.survey_items.count -# end.sum -# end.sum -# end -# student_response_counts = Subcategory.all.map do |subcategory| -# subcategory.measures.map do |measure| -# measure.student_survey_items.map do |survey_item| -# survey_item.survey_item_responses.where(school:, academic_year:).exclude_boston.count -# end.sum -# end.sum -# end - -# student_response_counts.each_with_index.map do |value, index| -# value.to_f / student_survey_items[index] / total_possible_student_responses * 100 -# end diff --git a/app/models/subcategory.rb b/app/models/subcategory.rb index 390482d5..29f36333 100644 --- a/app/models/subcategory.rb +++ b/app/models/subcategory.rb @@ -4,26 +4,31 @@ class Subcategory < ActiveRecord::Base has_many :measures def score(school:, academic_year:) - scores = measures.includes([:survey_items]).map do |measure| + scores = measures.map do |measure| measure.score(school:, academic_year:).average end scores = scores.reject(&:nil?) scores.average end - def student_response_rate(school:, academic_year:) - @student_response_rate ||= Hash.new do |memo, (school, academic_year)| - memo[[school, academic_year]] = StudentResponseRateCalculator.new(subcategory: self, school:, academic_year:) + def response_rate(school:, academic_year:) + @response_rate ||= Hash.new do |memo, (school, academic_year)| + memo[[school, academic_year]] = ResponseRate.find_by(subcategory: self, school:, academic_year:) end - @student_response_rate[[school, academic_year]] + if @response_rate[[school, academic_year]].nil? + @response_rate[[school, academic_year]] = create_response_rate(subcategory: self, school:, academic_year:) + end + + @response_rate[[school, academic_year]] end - def teacher_response_rate(school:, academic_year:) - @teacher_response_rate ||= Hash.new do |memo, (school, academic_year)| - memo[[school, academic_year]] = TeacherResponseRateCalculator.new(subcategory: self, school:, academic_year:) - end + private - @teacher_response_rate[[school, academic_year]] + def create_response_rate(subcategory:, school:, academic_year:) + student = StudentResponseRateCalculator.new(subcategory: self, school:, academic_year:) + teacher = TeacherResponseRateCalculator.new(subcategory: self, school:, academic_year:) + ResponseRate.create(school:, academic_year:, subcategory: self, student_response_rate: student.rate, teacher_response_rate: teacher.rate, + meets_student_threshold: student.meets_student_threshold?, meets_teacher_threshold: teacher.meets_teacher_threshold?) end end diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index 13e685dc..3e61a12b 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -5,6 +5,7 @@ class SurveyItemResponse < ActiveRecord::Base belongs_to :academic_year belongs_to :school belongs_to :survey_item + has_one :measure, through: :survey_item scope :exclude_boston, lambda { boston = District.find_by_name('Boston') diff --git a/app/presenters/subcategory_presenter.rb b/app/presenters/subcategory_presenter.rb index ce092760..3426cdc4 100644 --- a/app/presenters/subcategory_presenter.rb +++ b/app/presenters/subcategory_presenter.rb @@ -32,13 +32,13 @@ class SubcategoryPresenter def student_response_rate return 'N / A' if Respondent.where(school: @school, academic_year: @academic_year).count.zero? - "#{@subcategory.student_response_rate(school: @school, academic_year: @academic_year).rate}%" + "#{@subcategory.response_rate(school: @school, academic_year: @academic_year).student_response_rate.to_i}%" end def teacher_response_rate return 'N / A' if Respondent.where(school: @school, academic_year: @academic_year).count.zero? - "#{@subcategory.teacher_response_rate(school: @school, academic_year: @academic_year).rate}%" + "#{@subcategory.response_rate(school: @school, academic_year: @academic_year).teacher_response_rate.to_i}%" end def admin_collection_rate diff --git a/app/services/response_rate_loader.rb b/app/services/response_rate_loader.rb new file mode 100644 index 00000000..d04528db --- /dev/null +++ b/app/services/response_rate_loader.rb @@ -0,0 +1,34 @@ +class ResponseRateLoader + def self.refresh + schools = School.all + academic_years = AcademicYear.all + subcategories = Subcategory.all + + milford = School.find_by_slug 'milford-high-school' + + # ResponseRate.new(school:, academic_year:, subcategory:, student_response_rate: 50, teacher_response_rate: 50, + # meets_student_threshold: true, meets_teacher_threshold: true).save + + test_year = AcademicYear.find_by_range '2020-21' + subcategories.each do |subcategory| + schools.each do |school| + next if ENV['RAILS_ENV'] == 'test' && !(school == milford) + + academic_years.each do |academic_year| + next if ENV['RAILS_ENV'] == 'test' && !(academic_year == test_year) + + student = StudentResponseRateCalculator.new(subcategory:, school:, academic_year:) + teacher = TeacherResponseRateCalculator.new(subcategory:, school:, academic_year:) + + response_rate = ResponseRate.find_or_create_by!(subcategory:, school:, academic_year:) + + response_rate.student_response_rate = student.rate + response_rate.teacher_response_rate = teacher.rate + response_rate.meets_student_threshold = student.meets_student_threshold? + response_rate.meets_teacher_threshold = teacher.meets_teacher_threshold? + response_rate.save + end + end + end + end +end diff --git a/app/views/overview/index.html.erb b/app/views/overview/index.html.erb index 476a69d8..a7284ab8 100644 --- a/app/views/overview/index.html.erb +++ b/app/views/overview/index.html.erb @@ -1,105 +1,105 @@ <% content_for :navigation do %> -