From 2655a36bfce5cb8ec037191c55b3774871ae9ea4 Mon Sep 17 00:00:00 2001 From: rebuilt Date: Tue, 1 Feb 2022 15:28:25 +0100 Subject: [PATCH] Replace integer devision with float division for accurate response rate calculation --- app/models/response_rate.rb | 50 ++++++++++-------------------- app/models/survey_item_response.rb | 8 +++++ spec/models/response_rate_spec.rb | 15 +++++++-- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/app/models/response_rate.rb b/app/models/response_rate.rb index 20f39759..469fe5d5 100644 --- a/app/models/response_rate.rb +++ b/app/models/response_rate.rb @@ -6,27 +6,23 @@ class ResponseRate end def student - @student_response_rate ||= begin - return 0 unless student_survey_item_count.positive? + return 0 unless student_survey_item_count.positive? - average_responses_per_survey_item = student_response_count / student_survey_item_count + average_responses_per_survey_item = student_response_count / student_survey_item_count - return 0 unless total_possible_student_responses.positive? + return 0 unless total_possible_student_responses.positive? - (average_responses_per_survey_item / total_possible_student_responses * 100).round - end + (average_responses_per_survey_item / total_possible_student_responses * 100).round end def teacher - @teacher_response_rate ||= begin - return 0 unless teacher_survey_item_count.positive? + return 0 unless teacher_survey_item_count.positive? - average_responses_per_survey_item = teacher_response_count / teacher_survey_item_count + average_responses_per_survey_item = teacher_response_count / teacher_survey_item_count - return 0 unless total_possible_teacher_responses.positive? + return 0 unless total_possible_teacher_responses.positive? - (average_responses_per_survey_item / total_possible_teacher_responses * 100).round - end + (average_responses_per_survey_item / total_possible_teacher_responses * 100).round end private @@ -51,38 +47,24 @@ class ResponseRate end def student_response_count - @student_response_count ||= response_count do |measure| - next 0 unless measure.includes_student_survey_items? - - SurveyItemResponse.student_responses_for_measure(measure, @school, @academic_year).count - end + @student_response_count ||= SurveyItemResponse.student_responses_for_measures(@subcategory.measures, @school, + @academic_year).count.to_f end def teacher_response_count - @teacher_response_count ||= response_count do |measure| - next 0 unless measure.includes_teacher_survey_items? - - SurveyItemResponse.teacher_responses_for_measure(measure, @school, @academic_year).count - end - end - - def response_count(&block) - @subcategory.measures.map(&block).sum + @teacher_response_count ||= SurveyItemResponse.teacher_responses_for_measures(@subcategory.measures, @school, + @academic_year).count.to_f end def student_survey_item_count - @student_survey_item_count ||= survey_item_count do |measure| + @student_survey_item_count ||= @subcategory.measures.map do |measure| measure.student_survey_items.count - end + end.sum.to_f end def teacher_survey_item_count - @teacher_survey_item_count ||= survey_item_count do |measure| + @teacher_survey_item_count ||= @subcategory.measures.map do |measure| measure.teacher_survey_items.count - end - end - - def survey_item_count(&block) - @subcategory.measures.map(&block).sum + end.sum.to_f end end diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index 838bc481..801cff08 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -68,11 +68,19 @@ class SurveyItemResponse < ActiveRecord::Base for_measure(measure, school, academic_year) .where("survey_items.survey_item_id LIKE 't-%'") } + scope :teacher_responses_for_measures, lambda { |measures, school, academic_year| + for_measures(measures, school, academic_year) + .where("survey_items.survey_item_id LIKE 't-%'") + } scope :student_responses_for_measure, lambda { |measure, school, academic_year| for_measure(measure, school, academic_year) .where("survey_items.survey_item_id LIKE 's-%'") } + scope :student_responses_for_measures, lambda { |measures, school, academic_year| + for_measures(measures, school, academic_year) + .where("survey_items.survey_item_id LIKE 's-%'") + } def self.student_sufficient_data?(measure:, school:, academic_year:) if measure.includes_student_survey_items? student_survey_item_responses = SurveyItemResponse.student_responses_for_measure(measure, school, academic_year) diff --git a/spec/models/response_rate_spec.rb b/spec/models/response_rate_spec.rb index f703cae1..ed806c70 100644 --- a/spec/models/response_rate_spec.rb +++ b/spec/models/response_rate_spec.rb @@ -48,6 +48,7 @@ describe ResponseRate, type: :model do let(:insufficient_measure) { create(:measure, subcategory: subcategory) } let(:sufficient_teacher_survey_item_1) { create(:teacher_survey_item, measure: sufficient_measure_1) } let(:sufficient_teacher_survey_item_2) { create(:teacher_survey_item, measure: sufficient_measure_1) } + let(:sufficient_teacher_survey_item_3) { create(:teacher_survey_item, measure: sufficient_measure_1) } let(:sufficient_student_survey_item_1) { create(:student_survey_item, measure: sufficient_measure_1) } let(:insufficient_teacher_survey_item) { create(:teacher_survey_item, measure: insufficient_measure) } let(:insufficient_student_survey_item) { create(:student_survey_item, measure: insufficient_measure) } @@ -57,7 +58,7 @@ describe ResponseRate, type: :model do create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD, survey_item: sufficient_teacher_survey_item_1, academic_year: ay, school: school, likert_score: 1) create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD + 1, survey_item: sufficient_teacher_survey_item_2, - academic_year: ay, school: school, likert_score: 1) + academic_year: ay, school: school, likert_score: 1) create_list(:survey_item_response, SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD, survey_item: sufficient_student_survey_item_1, academic_year: ay, school: school, likert_score: 4) create_list(:survey_item_response, SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD - 1, @@ -66,11 +67,21 @@ describe ResponseRate, type: :model do survey_item: insufficient_student_survey_item, academic_year: ay, school: school, likert_score: 1) end - context 'when the average number of student responses per question in a subcategory is equal to the student response threshold' do + context 'when the average number of teacher responses per question in a subcategory is equal to the teacher response threshold' do it 'returns 100 percent' do expect(ResponseRate.new(subcategory: subcategory, school: school, academic_year: ay).teacher).to eq 100 end end + context 'when the average number of teacher responses is 77.9, the response rate averages up to 78 percent' do + before do + create_list(:survey_item_response, 2, survey_item: sufficient_teacher_survey_item_3, + academic_year: ay, school: school, likert_score: 1) + end + it 'returns 10 percent' do + expect(ResponseRate.new(subcategory: subcategory, school: school, + academic_year: ay).teacher).to eq 78 + end + end end end