diff --git a/app/models/survey_item_response.rb b/app/models/survey_item_response.rb index c1d8d270..ed559983 100644 --- a/app/models/survey_item_response.rb +++ b/app/models/survey_item_response.rb @@ -48,7 +48,7 @@ class SurveyItemResponse < ActiveRecord::Base 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) + ).where("student_races.race_id": race.id).group(:survey_item).having("count(*) >= 10").average(:likert_score) } def self.grouped_responses(school:, academic_year:) diff --git a/app/presenters/analyze/background_presenter.rb b/app/presenters/analyze/background_presenter.rb index 4a4b2462..586c0ab0 100644 --- a/app/presenters/analyze/background_presenter.rb +++ b/app/presenters/analyze/background_presenter.rb @@ -19,7 +19,7 @@ class Analyze::BackgroundPresenter end def grouped_chart_column_width - graph_width / data_sources + graph_width / num_of_columns end def column_end_x(position) @@ -37,8 +37,4 @@ class Analyze::BackgroundPresenter def zone_label_y(position) 8.5 * (position + position - 1) end - - def data_sources - num_of_columns - end end diff --git a/app/presenters/analyze/graph/all_data.rb b/app/presenters/analyze/graph/all_data.rb index d360e66b..6d5955c1 100644 --- a/app/presenters/analyze/graph/all_data.rb +++ b/app/presenters/analyze/graph/all_data.rb @@ -5,6 +5,10 @@ module Analyze class AllData include Analyze::Graph::Column + def label + ["All", "Data"] + end + def to_s %w[All Data] end @@ -13,8 +17,12 @@ module Analyze "all-data" end + def type + :all_data + end + def columns - [AllStudent, AllTeacher, AllAdmin, Analyze::Graph::Column::AllData] + [AllStudent.new, AllTeacher.new, AllAdmin.new, AllData.new] end def source @@ -24,6 +32,26 @@ module Analyze def slice Analyze::Slice::AllData.new end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + scores = academic_years.map do |academic_year| + measure.score(school:, academic_year:) + end + + scores.none? { |score| score.meets_student_threshold? || score.meets_teacher_threshold? || score.meets_admin_data_threshold? } + end + + def insufficiency_message + ["survey response", "rate below 25%"] + end + + def score(measure:, school:, academic_year:) + measure.score(school:, academic_year:) + end end end end diff --git a/app/presenters/analyze/graph/all_parent.rb b/app/presenters/analyze/graph/all_parent.rb new file mode 100644 index 00000000..48ba5924 --- /dev/null +++ b/app/presenters/analyze/graph/all_parent.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Analyze + module Graph + class AllParent + def initialize(scales:) + @scales = scales + end + + def to_s + "All Data" + end + + def slug + "all-data" + end + + def source + Analyze::Source::AllData.new(slices: [slice]) + end + + def slice + Analyze::Slice::AllData.new + end + end + end +end diff --git a/app/presenters/analyze/graph/column/all_admin.rb b/app/presenters/analyze/graph/column/all_admin.rb index 159e37df..4cb84fda 100644 --- a/app/presenters/analyze/graph/column/all_admin.rb +++ b/app/presenters/analyze/graph/column/all_admin.rb @@ -3,7 +3,7 @@ module Analyze module Graph module Column - class AllAdmin < GroupedBarColumnPresenter + class AllAdmin def label %w[School Data] end @@ -12,11 +12,11 @@ module Analyze "school data" end - def show_irrelevancy_message? + def show_irrelevancy_message?(measure:) !measure.includes_admin_data_items? end - def show_insufficient_data_message? + def show_insufficient_data_message?(measure:, school:, academic_years:) !academic_years.any? do |year| measure.sufficient_admin_data?(school:, academic_year: year) end @@ -26,7 +26,7 @@ module Analyze ["data not", "available"] end - def score(academic_year) + def score(measure:, school:, academic_year:) measure.admin_score(school:, academic_year:) end diff --git a/app/presenters/analyze/graph/column/all_data.rb b/app/presenters/analyze/graph/column/all_data.rb index aba0ac86..718bae3f 100644 --- a/app/presenters/analyze/graph/column/all_data.rb +++ b/app/presenters/analyze/graph/column/all_data.rb @@ -1,16 +1,16 @@ module Analyze module Graph module Column - class AllData < GroupedBarColumnPresenter + class AllData def label %w[All Data] end - def show_irrelevancy_message? + def show_irrelevancy_message?(measure:) false end - def show_insufficient_data_message? + def show_insufficient_data_message?(measure:, school:, academic_years:) scores = academic_years.map do |year| measure.score(school:, academic_year: year) end @@ -20,7 +20,7 @@ module Analyze end end - def score(academic_year) + def score(measure:, school:, academic_year:) measure.score(school:, academic_year:) || 0 end @@ -32,7 +32,7 @@ module Analyze "student surveys" end - def n_size(academic_year) + def n_size(measure:, school:, academic_year:) SurveyItemResponse.where(survey_item: measure.student_survey_items, school:, grade: grades, academic_year:).select(:response_id).distinct.count end diff --git a/app/presenters/analyze/graph/column/all_student.rb b/app/presenters/analyze/graph/column/all_student.rb index 358ad321..011dc38c 100644 --- a/app/presenters/analyze/graph/column/all_student.rb +++ b/app/presenters/analyze/graph/column/all_student.rb @@ -3,16 +3,24 @@ module Analyze module Graph module Column - class AllStudent < GroupedBarColumnPresenter + class AllStudent def label - %w[All Students] + ["All", "Students"] end - def show_irrelevancy_message? + def basis + "student surveys" + end + + def insufficiency_message + ["survey response", "rate below 25%"] + end + + def show_irrelevancy_message?(measure:) !measure.includes_student_survey_items? end - def show_insufficient_data_message? + def show_insufficient_data_message?(measure:, school:, academic_years:) scores = academic_years.map do |academic_year| measure.student_score(school:, academic_year:) end @@ -20,7 +28,7 @@ module Analyze scores.none? { |score| score.meets_student_threshold? } end - def score(academic_year) + def score(measure:, school:, academic_year:) measure.student_score(school:, academic_year:) end @@ -28,7 +36,8 @@ module Analyze :student end - def n_size(academic_year) + def n_size(measure:, school:, academic_year:) + grades = Respondent.by_school_and_year(school:, academic_year:)&.enrollment_by_grade&.keys SurveyItemResponse.where(survey_item: measure.student_survey_items, school:, grade: grades, academic_year:).select(:response_id).distinct.count end diff --git a/app/presenters/analyze/graph/column/all_survey_data.rb b/app/presenters/analyze/graph/column/all_survey_data.rb index 004bd79b..b3ef1698 100644 --- a/app/presenters/analyze/graph/column/all_survey_data.rb +++ b/app/presenters/analyze/graph/column/all_survey_data.rb @@ -3,34 +3,32 @@ module Analyze module Graph module Column - class AllSurveyData < GroupedBarColumnPresenter + class AllSurveyData def label %w[Survey Data] end - def show_irrelevancy_message? - false + def basis + "survey data" end - def show_insufficient_data_message? - scores = academic_years.map do |year| - combined_score(school:, academic_year: year) + def show_irrelevancy_message?(measure:) + !measure.includes_teacher_survey_items? || !measure.includes_student_survey_items? || !measure.includes_parent_survey_items? + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + scores = academic_years.map do |academic_year| + score(measure:, school:, academic_year:) end scores.all? { |score| !score.meets_student_threshold? && !score.meets_teacher_threshold? } end - def score(academic_year) - combined_score(school:, academic_year:) - end - - def type - :all_survey_data + def insufficiency_message + ["survey response", "rate below 25%"] end - private - - def combined_score(school:, academic_year:) + def score(measure:, school:, academic_year:) teacher_score = measure.teacher_score(school:, academic_year:) student_score = measure.student_score(school:, academic_year:) @@ -41,6 +39,10 @@ module Analyze combined_score = Score.new(average:, meets_student_threshold: student_score.meets_student_threshold, meets_teacher_threshold: teacher_score.meets_teacher_threshold) end + + def type + :all_survey_data + end end end end diff --git a/app/presenters/analyze/graph/column/all_teacher.rb b/app/presenters/analyze/graph/column/all_teacher.rb index 4495bfe5..66ff7c7c 100644 --- a/app/presenters/analyze/graph/column/all_teacher.rb +++ b/app/presenters/analyze/graph/column/all_teacher.rb @@ -3,7 +3,7 @@ module Analyze module Graph module Column - class AllTeacher < GroupedBarColumnPresenter + class AllTeacher def label %w[All Teachers] end @@ -12,11 +12,15 @@ module Analyze "teacher surveys" end - def show_irrelevancy_message? + def insufficiency_message + ["survey response", "rate below 25%"] + end + + def show_irrelevancy_message?(measure:) !measure.includes_teacher_survey_items? end - def show_insufficient_data_message? + def show_insufficient_data_message?(measure:, school:, academic_years:) scores = academic_years.map do |year| measure.score(school:, academic_year: year) end @@ -24,7 +28,7 @@ module Analyze scores.all? { |score| !score.meets_teacher_threshold? } end - def score(academic_year) + def score(measure:, school:, academic_year:) measure.teacher_score(school:, academic_year:) end @@ -32,7 +36,7 @@ module Analyze :teacher end - def n_size(academic_year) + def n_size(measure:, school:, academic_year:) SurveyItemResponse.where(survey_item: measure.teacher_survey_items, school:, academic_year:).pluck(:response_id).uniq.count end diff --git a/app/presenters/analyze/graph/column/column_base.rb b/app/presenters/analyze/graph/column/column_base.rb new file mode 100644 index 00000000..f15611ae --- /dev/null +++ b/app/presenters/analyze/graph/column/column_base.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class ColumnBase + def label + raise NotImplementedError + end + + def basis + raise NotImplementedError + end + + def show_irrelevancy_message?(measure:) + raise NotImplementedError + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + raise NotImplementedError + end + + def insufficiency_message + raise NotImplementedError + end + + def score(measure:, school:, academic_year:) + raise NotImplementedError + end + + def type + raise NotImplementedError + end + + def n_size(measure:, school:, academic_year:) + raise NotImplementedError + end + + def bubble_up_averages(measure:, averages:) + measure.student_scales.map do |scale| + scale.survey_items.map do |survey_item| + averages[survey_item] + end.remove_blanks.average + end.remove_blanks.average + end + + def grades(school:, academic_year:) + Respondent.by_school_and_year(school:, academic_year:)&.enrollment_by_grade&.keys + end + end + end + end +end diff --git a/app/presenters/analyze/graph/column/ell.rb b/app/presenters/analyze/graph/column/ell.rb new file mode 100644 index 00000000..9fa549ef --- /dev/null +++ b/app/presenters/analyze/graph/column/ell.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class Ell < ColumnBase + attr_reader :ell + + def initialize(ell:) + @ell = ell + end + + def label + ["#{ell.designation}"] + end + + def basis + "student" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def type + :student + end + + def n_size(measure:, school:, academic_year:) + SurveyItemResponse.where(ell:, survey_item: measure.student_survey_items, school:, grade: grades(school:, academic_year:), + academic_year:).select(:response_id).distinct.count + end + + def score(measure:, school:, academic_year:) + meets_student_threshold = sufficient_student_responses?(measure:, school:, academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + + averages = SurveyItemResponse.averages_for_ell(measure.student_survey_items, school, academic_year, + ell) + average = bubble_up_averages(measure:, averages:).round(2) + + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) + end + + def sufficient_student_responses?(measure:, school:, academic_year:) + return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? + + yearly_counts = SurveyItemResponse.where(school:, academic_year:, + ell:, survey_item: measure.student_survey_items).group(:ell).select(:response_id).distinct(:response_id).count + yearly_counts.any? do |count| + count[1] >= 10 + end + end + end + end + end +end diff --git a/app/presenters/analyze/graph/column/ell_column/ell.rb b/app/presenters/analyze/graph/column/ell_column/ell.rb deleted file mode 100644 index cba07408..00000000 --- a/app/presenters/analyze/graph/column/ell_column/ell.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module EllColumn - class Ell < GroupedBarColumnPresenter - include Analyze::Graph::Column::EllColumn::ScoreForEll - include Analyze::Graph::Column::EllColumn::EllCount - def label - %w[ELL] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def ell - ::Ell.find_by_slug "ell" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/ell_column/ell_count.rb b/app/presenters/analyze/graph/column/ell_column/ell_count.rb deleted file mode 100644 index 582d7221..00000000 --- a/app/presenters/analyze/graph/column/ell_column/ell_count.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Analyze - module Graph - module Column - module EllColumn - module EllCount - def type - :student - end - - def n_size(academic_year) - SurveyItemResponse.where(ell:, survey_item: measure.student_survey_items, school:, grade: grades, - academic_year:).select(:response_id).distinct.count - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/ell_column/not_ell.rb b/app/presenters/analyze/graph/column/ell_column/not_ell.rb deleted file mode 100644 index 1c3ca596..00000000 --- a/app/presenters/analyze/graph/column/ell_column/not_ell.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module EllColumn - class NotEll < GroupedBarColumnPresenter - include Analyze::Graph::Column::EllColumn::ScoreForEll - include Analyze::Graph::Column::EllColumn::EllCount - def label - ["Not ELL"] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def ell - ::Ell.find_by_slug "not-ell" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/ell_column/score_for_ell.rb b/app/presenters/analyze/graph/column/ell_column/score_for_ell.rb deleted file mode 100644 index 97589b90..00000000 --- a/app/presenters/analyze/graph/column/ell_column/score_for_ell.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Analyze - module Graph - module Column - module EllColumn - module ScoreForEll - def score(academic_year) - meets_student_threshold = sufficient_student_responses?(academic_year:) - return Score::NIL_SCORE unless meets_student_threshold - - averages = SurveyItemResponse.averages_for_ell(measure.student_survey_items, school, academic_year, - ell) - average = bubble_up_averages(averages:).round(2) - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold:, - meets_admin_data_threshold: false) - end - - def bubble_up_averages(averages:) - measure.student_scales.map do |scale| - scale.survey_items.map do |survey_item| - averages[survey_item] - 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:, - ell:, survey_item: measure.student_survey_items).group(:ell).select(:response_id).distinct(:response_id).count - yearly_counts.any? do |count| - count[1] >= 10 - end - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/ell_column/unknown.rb b/app/presenters/analyze/graph/column/ell_column/unknown.rb deleted file mode 100644 index 37f077ae..00000000 --- a/app/presenters/analyze/graph/column/ell_column/unknown.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module EllColumn - class Unknown < GroupedBarColumnPresenter - include Analyze::Graph::Column::EllColumn::ScoreForEll - include Analyze::Graph::Column::EllColumn::EllCount - def label - %w[Unknown] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def ell - ::Ell.find_by_slug "unknown" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/gender.rb b/app/presenters/analyze/graph/column/gender.rb new file mode 100644 index 00000000..cdf974f1 --- /dev/null +++ b/app/presenters/analyze/graph/column/gender.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class Gender < ColumnBase + attr_reader :gender + + def initialize(gender:) + @gender = gender + end + + def label + ["#{gender.designation}"] + end + + def basis + "student surveys" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def type + :student + end + + def n_size(measure:, school:, academic_year:) + SurveyItemResponse.where(gender:, survey_item: measure.student_survey_items, school:, grade: grades(school:, academic_year:), + academic_year:).select(:response_id).distinct.count + end + + def score(measure:, school:, academic_year:) + meets_student_threshold = sufficient_student_responses?(measure:, school:, 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(measure:, averages:).round(2) + + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) + end + + def sufficient_student_responses?(measure:, school:, 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| + count[1] >= 10 + end + end + end + end + end +end diff --git a/app/presenters/analyze/graph/column/gender_column/female.rb b/app/presenters/analyze/graph/column/gender_column/female.rb deleted file mode 100644 index 54941fbf..00000000 --- a/app/presenters/analyze/graph/column/gender_column/female.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module GenderColumn - class Female < GroupedBarColumnPresenter - include Analyze::Graph::Column::GenderColumn::ScoreForGender - include Analyze::Graph::Column::GenderColumn::GenderCount - def label - %w[Female] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def gender - ::Gender.find_by_qualtrics_code 1 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/gender_column/gender_count.rb b/app/presenters/analyze/graph/column/gender_column/gender_count.rb deleted file mode 100644 index ad0c4e72..00000000 --- a/app/presenters/analyze/graph/column/gender_column/gender_count.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Analyze - module Graph - module Column - module GenderColumn - module GenderCount - def type - :student - end - - def n_size(academic_year) - SurveyItemResponse.where(gender:, survey_item: measure.student_survey_items, school:, grade: grades, - academic_year:).select(:response_id).distinct.count - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/gender_column/male.rb b/app/presenters/analyze/graph/column/gender_column/male.rb deleted file mode 100644 index 031b91e6..00000000 --- a/app/presenters/analyze/graph/column/gender_column/male.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module GenderColumn - class Male < GroupedBarColumnPresenter - include Analyze::Graph::Column::GenderColumn::ScoreForGender - include Analyze::Graph::Column::GenderColumn::GenderCount - def label - %w[Male] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def gender - ::Gender.find_by_qualtrics_code 2 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/gender_column/non_binary.rb b/app/presenters/analyze/graph/column/gender_column/non_binary.rb deleted file mode 100644 index 8b3c8547..00000000 --- a/app/presenters/analyze/graph/column/gender_column/non_binary.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module GenderColumn - class NonBinary < GroupedBarColumnPresenter - include Analyze::Graph::Column::GenderColumn::ScoreForGender - include Analyze::Graph::Column::GenderColumn::GenderCount - def label - %w[Non-Binary] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def gender - ::Gender.find_by_qualtrics_code 4 - end - end - end - end - end -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 deleted file mode 100644 index b7f8c77d..00000000 --- a/app/presenters/analyze/graph/column/gender_column/score_for_gender.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Analyze - module Graph - module Column - module GenderColumn - module ScoreForGender - def score(academic_year) - 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) - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold:, - meets_admin_data_threshold: false) - end - - def bubble_up_averages(averages:) - measure.student_scales.map do |scale| - scale.survey_items.map do |survey_item| - averages[survey_item] - 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:, - gender:, survey_item: measure.student_survey_items).group(:gender).select(:response_id).distinct(:response_id).count - yearly_counts.any? do |count| - count[1] >= 10 - end - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/gender_column/unknown.rb b/app/presenters/analyze/graph/column/gender_column/unknown.rb deleted file mode 100644 index d954cece..00000000 --- a/app/presenters/analyze/graph/column/gender_column/unknown.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module GenderColumn - class Unknown < GroupedBarColumnPresenter - include Analyze::Graph::Column::GenderColumn::ScoreForGender - include Analyze::Graph::Column::GenderColumn::GenderCount - def label - %w[Unknown] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def gender - ::Gender.find_by_qualtrics_code 99 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade.rb b/app/presenters/analyze/graph/column/grade.rb new file mode 100644 index 00000000..31c03ea5 --- /dev/null +++ b/app/presenters/analyze/graph/column/grade.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class Grade < ColumnBase + attr_reader :grade + + def initialize(grade:) + @grade = grade + end + + def label + ["#{grade}"] + end + + def basis + "student surveys" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def type + :student + end + + def n_size(measure:, school:, academic_year:) + SurveyItemResponse.where(grade:, survey_item: measure.student_survey_items, school:, + academic_year:).select(:response_id).distinct.count + end + + def score(measure:, school:, academic_year:) + meets_student_threshold = sufficient_student_responses?(measure:, school:, academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + + averages = SurveyItemResponse.averages_for_grade(measure.student_survey_items, school, + academic_year, grade) + average = bubble_up_averages(measure:, averages:).round(2) + + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) + end + + def sufficient_student_responses?(measure:, school:, 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 +end diff --git a/app/presenters/analyze/graph/column/grade/eight.rb b/app/presenters/analyze/graph/column/grade/eight.rb deleted file mode 100644 index 8d4bf62f..00000000 --- a/app/presenters/analyze/graph/column/grade/eight.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Eight < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 8] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 8 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/eleven.rb b/app/presenters/analyze/graph/column/grade/eleven.rb deleted file mode 100644 index dba11366..00000000 --- a/app/presenters/analyze/graph/column/grade/eleven.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Eleven < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 11] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 11 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/five.rb b/app/presenters/analyze/graph/column/grade/five.rb deleted file mode 100644 index 30033e31..00000000 --- a/app/presenters/analyze/graph/column/grade/five.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Five < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 5] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 5 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/four.rb b/app/presenters/analyze/graph/column/grade/four.rb deleted file mode 100644 index 1f563742..00000000 --- a/app/presenters/analyze/graph/column/grade/four.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Four < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 4] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 4 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/grade_count.rb b/app/presenters/analyze/graph/column/grade/grade_count.rb deleted file mode 100644 index a12aeba7..00000000 --- a/app/presenters/analyze/graph/column/grade/grade_count.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Analyze - module Graph - module Column - module Grade - module GradeCount - def type - :student - end - - def n_size(academic_year) - SurveyItemResponse.where(grade:, survey_item: measure.student_survey_items, school:, - academic_year:).select(:response_id).distinct.count - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/nine.rb b/app/presenters/analyze/graph/column/grade/nine.rb deleted file mode 100644 index 9c3a9397..00000000 --- a/app/presenters/analyze/graph/column/grade/nine.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Nine < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 9] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 9 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/one.rb b/app/presenters/analyze/graph/column/grade/one.rb deleted file mode 100644 index b1e3bcde..00000000 --- a/app/presenters/analyze/graph/column/grade/one.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class One < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 1] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 1 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/p_k.rb b/app/presenters/analyze/graph/column/grade/p_k.rb deleted file mode 100644 index 9c3e4aaa..00000000 --- a/app/presenters/analyze/graph/column/grade/p_k.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class PK < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Pre-K] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - -1 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/score_for_grade.rb b/app/presenters/analyze/graph/column/grade/score_for_grade.rb deleted file mode 100644 index 38548c47..00000000 --- a/app/presenters/analyze/graph/column/grade/score_for_grade.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Analyze - module Graph - module Column - module Grade - module ScoreForGrade - def score(academic_year) - 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_year, grade) - average = bubble_up_averages(averages:).round(2) - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold:, - meets_admin_data_threshold: false) - end - - def bubble_up_averages(averages:) - measure.student_scales.map do |scale| - scale.survey_items.map do |survey_item| - averages[survey_item] - 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 - end -end diff --git a/app/presenters/analyze/graph/column/grade/seven.rb b/app/presenters/analyze/graph/column/grade/seven.rb deleted file mode 100644 index 6aa5a818..00000000 --- a/app/presenters/analyze/graph/column/grade/seven.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Seven < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 7] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 7 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/six.rb b/app/presenters/analyze/graph/column/grade/six.rb deleted file mode 100644 index 1e40703b..00000000 --- a/app/presenters/analyze/graph/column/grade/six.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Six < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 6] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 6 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/ten.rb b/app/presenters/analyze/graph/column/grade/ten.rb deleted file mode 100644 index 45839d31..00000000 --- a/app/presenters/analyze/graph/column/grade/ten.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Ten < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 10] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 10 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/three.rb b/app/presenters/analyze/graph/column/grade/three.rb deleted file mode 100644 index 44a32772..00000000 --- a/app/presenters/analyze/graph/column/grade/three.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Three < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 3] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 3 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/twelve.rb b/app/presenters/analyze/graph/column/grade/twelve.rb deleted file mode 100644 index 0a8f7a26..00000000 --- a/app/presenters/analyze/graph/column/grade/twelve.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Twelve < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 12] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 12 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/two.rb b/app/presenters/analyze/graph/column/grade/two.rb deleted file mode 100644 index 195661e1..00000000 --- a/app/presenters/analyze/graph/column/grade/two.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Two < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Grade 2] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 2 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grade/zero.rb b/app/presenters/analyze/graph/column/grade/zero.rb deleted file mode 100644 index 611f9d3a..00000000 --- a/app/presenters/analyze/graph/column/grade/zero.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module Grade - class Zero < GroupedBarColumnPresenter - include Analyze::Graph::Column::Grade::ScoreForGrade - include Analyze::Graph::Column::Grade::GradeCount - def label - %w[Kindergarten] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def grade - 0 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb b/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb index 08480c57..4359f61c 100644 --- a/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb +++ b/app/presenters/analyze/graph/column/grouped_bar_column_presenter.rb @@ -7,9 +7,9 @@ module Analyze include AnalyzeHelper attr_reader :measure_name, :measure_id, :category, :position, :measure, :school, :academic_years, - :number_of_columns + :number_of_columns, :config - def initialize(measure:, school:, academic_years:, position:, number_of_columns:) + def initialize(measure:, school:, academic_years:, position:, number_of_columns:, config:) @measure = measure @measure_name = @measure.name @measure_id = @measure.measure_id @@ -18,12 +18,13 @@ module Analyze @academic_years = academic_years @position = position @number_of_columns = number_of_columns + @config = config end def bars @bars ||= academic_years.map.with_index do |academic_year, index| Analyze::BarPresenter.new(measure:, academic_year:, - score: score(academic_year), + score: score(academic_year:), x_position: bar_x(index), color: bar_color(academic_year)) end.reject(&:blank?).select { |bar| bar.score.average&.positive? } @@ -31,31 +32,43 @@ module Analyze end def label - raise NotImplementedError + config.label end def show_irrelevancy_message? - raise NotImplementedError + config.show_irrelevancy_message?(measure:) end def show_insufficient_data_message? - raise NotImplementedError + config.show_insufficient_data_message?(measure:, school:, academic_years:) end - def score(academic_year) - raise NotImplementedError + def score(academic_year:) + config.score(measure:, school:, academic_year:) end - def n_size(academic_year) - raise NotImplementedError + def n_size(academic_year:) + config.n_size(measure:, school:, academic_year:) end def basis - "student surveys" + config.basis end def type - raise NotImplementedError + config.type + end + + def insufficiency_message + config.insufficiency_message + end + + def show_popover? + %i[student teacher].include? type + end + + def popover_content(academic_year) + "#{n_size(academic_year:)} #{type.to_s.capitalize}s" end def column_midpoint @@ -107,31 +120,12 @@ module Analyze number_of_columns end - def show_popover? - %i[student teacher].include? type - end - - def popover_content(academic_year) - "#{n_size(academic_year)} #{type.to_s.capitalize}s" - end - - def insufficiency_message - ["survey response", "rate below 25%"] - end - def grades Respondent.by_school_and_year(school:, academic_year: academic_years)&.enrollment_by_grade&.keys end private - # YearlyScore = Struct.new(:year, :score) - # def yearly_scores - # @yearly_scores ||= academic_years.each.map do |year| - # YearlyScore.new(year, score(year)) - # end.reject { |year| year.score.nil? || year.score.blank? } - # end - def bar_color(year) @available_academic_years ||= AcademicYear.order(:range).all colors[@available_academic_years.find_index(year)] diff --git a/app/presenters/analyze/graph/column/income.rb b/app/presenters/analyze/graph/column/income.rb new file mode 100644 index 00000000..18c6e470 --- /dev/null +++ b/app/presenters/analyze/graph/column/income.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class Income < ColumnBase + attr_reader :income + + def initialize(income:) + @income = income + end + + def label + income.designation.split(' ', 2) + end + + def basis + "student surveys" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def type + :student + end + + def n_size(measure:, school:, academic_year:) + SurveyItemResponse.where(income:, survey_item: measure.student_survey_items, school:, grade: grades(school:, academic_year:), + academic_year:).select(:response_id).distinct.count + end + + def score(measure:, school:, academic_year:) + meets_student_threshold = sufficient_student_responses?(measure:, school:, 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(measure:, averages:).round(2) + + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) + end + + def sufficient_student_responses?(measure:, school:, 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| + count[1] >= 10 + end + end + end + end + end +end diff --git a/app/presenters/analyze/graph/column/income_column/disadvantaged.rb b/app/presenters/analyze/graph/column/income_column/disadvantaged.rb deleted file mode 100644 index 6765d641..00000000 --- a/app/presenters/analyze/graph/column/income_column/disadvantaged.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module IncomeColumn - class Disadvantaged < GroupedBarColumnPresenter - include Analyze::Graph::Column::IncomeColumn::ScoreForIncome - include Analyze::Graph::Column::IncomeColumn::IncomeCount - def label - %w[Economically Disadvantaged] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def income - Income.find_by_designation "Economically Disadvantaged - Y" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/income_column/income_count.rb b/app/presenters/analyze/graph/column/income_column/income_count.rb deleted file mode 100644 index 886459d1..00000000 --- a/app/presenters/analyze/graph/column/income_column/income_count.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Analyze - module Graph - module Column - module IncomeColumn - module IncomeCount - def type - :student - end - - def n_size(academic_year) - SurveyItemResponse.where(income:, survey_item: measure.student_survey_items, school:, grade: grades, - academic_year:).select(:response_id).distinct.count - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/income_column/not_disadvantaged.rb b/app/presenters/analyze/graph/column/income_column/not_disadvantaged.rb deleted file mode 100644 index cfca2baf..00000000 --- a/app/presenters/analyze/graph/column/income_column/not_disadvantaged.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module IncomeColumn - class NotDisadvantaged < GroupedBarColumnPresenter - include Analyze::Graph::Column::IncomeColumn::ScoreForIncome - include Analyze::Graph::Column::IncomeColumn::IncomeCount - def label - ["Not Economically", "Disadvantaged"] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def income - Income.find_by_designation "Economically Disadvantaged - N" - end - 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 deleted file mode 100644 index d1580f99..00000000 --- a/app/presenters/analyze/graph/column/income_column/score_for_income.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Analyze - module Graph - module Column - module IncomeColumn - module ScoreForIncome - def score(academic_year) - 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) - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold:, - meets_admin_data_threshold: false) - end - - def bubble_up_averages(averages:) - measure.student_scales.map do |scale| - scale.survey_items.map do |survey_item| - averages[survey_item] - 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:, - income:, survey_item: measure.student_survey_items).group(:income).select(:response_id).distinct(:response_id).count - yearly_counts.any? do |count| - count[1] >= 10 - end - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/income_column/unknown.rb b/app/presenters/analyze/graph/column/income_column/unknown.rb deleted file mode 100644 index 7a03580e..00000000 --- a/app/presenters/analyze/graph/column/income_column/unknown.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module IncomeColumn - class Unknown < GroupedBarColumnPresenter - include Analyze::Graph::Column::IncomeColumn::ScoreForIncome - include Analyze::Graph::Column::IncomeColumn::IncomeCount - def label - ["Unknown"] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def income - Income.find_by_designation "Unknown" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/parent/scale.rb b/app/presenters/analyze/graph/column/parent/scale.rb new file mode 100644 index 00000000..6f0d9657 --- /dev/null +++ b/app/presenters/analyze/graph/column/parent/scale.rb @@ -0,0 +1,44 @@ +module Analyze + module Graph + module Column + module Parent + class Scale + attr_reader :scale + + def initialize(scale:) + @scale = scale + end + + def label + scale.name.split("-") + end + + def basis + "parent data" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def insufficiency_message + ["data not", "available"] + end + + def score(measure:, school:, academic_year:) + average = scale.parent_score(school:, academic_year:) + Score.new(average:, meets_teacher_threshold: true, meets_student_threshold: true, meets_admin_data_threshold: true) + end + + def type + :parent + end + end + end + end + end +end diff --git a/app/presenters/analyze/graph/column/race.rb b/app/presenters/analyze/graph/column/race.rb new file mode 100644 index 00000000..23ec9fe8 --- /dev/null +++ b/app/presenters/analyze/graph/column/race.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class Race < ColumnBase + attr_reader :race + + def initialize(race:) + @race = race + end + + def label + tmp = race.designation.split("or").first + tmp.split(" ", 2) + end + + def basis + "student surveys" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def type + :student + end + + def n_size(measure:, school:, academic_year:) + 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:, + survey_item: measure.student_survey_items + ).where("student_races.race_id": race.id).select(:response_id).distinct.count + end + + def score(measure:, school:, academic_year:) + meets_student_threshold = sufficient_student_responses?(measure:, school:, academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + + measure.student_survey_items + + averages = SurveyItemResponse.averages_for_race(school, academic_year, race) + average = bubble_up_averages(measure:, averages:).round(2) + + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) + end + + def sufficient_student_responses?(measure:, school:, 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 + end +end diff --git a/app/presenters/analyze/graph/column/race_column/american_indian.rb b/app/presenters/analyze/graph/column/race_column/american_indian.rb deleted file mode 100644 index b5d2af8d..00000000 --- a/app/presenters/analyze/graph/column/race_column/american_indian.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class AmericanIndian < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[American Indian] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 1 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/asian.rb b/app/presenters/analyze/graph/column/race_column/asian.rb deleted file mode 100644 index 7b0af7f8..00000000 --- a/app/presenters/analyze/graph/column/race_column/asian.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class Asian < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[Asian] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 2 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/black.rb b/app/presenters/analyze/graph/column/race_column/black.rb deleted file mode 100644 index 72046c97..00000000 --- a/app/presenters/analyze/graph/column/race_column/black.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class Black < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[Black] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 3 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/hispanic.rb b/app/presenters/analyze/graph/column/race_column/hispanic.rb deleted file mode 100644 index 6f92a77e..00000000 --- a/app/presenters/analyze/graph/column/race_column/hispanic.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class Hispanic < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[Hispanic] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 4 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/middle_eastern.rb b/app/presenters/analyze/graph/column/race_column/middle_eastern.rb deleted file mode 100644 index 36955bf2..00000000 --- a/app/presenters/analyze/graph/column/race_column/middle_eastern.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class MiddleEastern < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - - def label - %w[Middle Eastern] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 8 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/multiracial.rb b/app/presenters/analyze/graph/column/race_column/multiracial.rb deleted file mode 100644 index c150cea1..00000000 --- a/app/presenters/analyze/graph/column/race_column/multiracial.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class Multiracial < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[Multiracial] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 100 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/race_count.rb b/app/presenters/analyze/graph/column/race_column/race_count.rb deleted file mode 100644 index 17a59f55..00000000 --- a/app/presenters/analyze/graph/column/race_column/race_count.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Analyze - module Graph - module Column - module RaceColumn - module RaceCount - def type - :student - end - - def n_size(academic_year) - 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:, - survey_item: measure.student_survey_items - ).where("student_races.race_id": race.id).select(:response_id).distinct.count - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/unknown.rb b/app/presenters/analyze/graph/column/race_column/unknown.rb deleted file mode 100644 index 8c6b786f..00000000 --- a/app/presenters/analyze/graph/column/race_column/unknown.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class Unknown < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[Not Listed] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 99 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/race_column/white.rb b/app/presenters/analyze/graph/column/race_column/white.rb deleted file mode 100644 index 221ecc8b..00000000 --- a/app/presenters/analyze/graph/column/race_column/white.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module RaceColumn - class White < GroupedBarColumnPresenter - include Analyze::Graph::Column::ScoreForRace - include Analyze::Graph::Column::RaceColumn::RaceCount - def label - %w[White] - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def race - Race.find_by_qualtrics_code 5 - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/score_for_race.rb b/app/presenters/analyze/graph/column/score_for_race.rb deleted file mode 100644 index 978d511c..00000000 --- a/app/presenters/analyze/graph/column/score_for_race.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Analyze - module Graph - module Column - module ScoreForRace - def score(academic_year) - meets_student_threshold = sufficient_student_responses?(academic_year:) - return Score::NIL_SCORE unless meets_student_threshold - - survey_items = measure.student_survey_items - - averages = SurveyItemResponse.averages_for_race(school, academic_year, race) - average = bubble_up_averages(averages:).round(2) - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold:, - meets_admin_data_threshold: false) - end - - def bubble_up_averages(averages:) - measure.student_scales.map do |scale| - scale.survey_items.map do |survey_item| - averages[survey_item.id] - 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? - - 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 - end -end diff --git a/app/presenters/analyze/graph/column/sped.rb b/app/presenters/analyze/graph/column/sped.rb new file mode 100644 index 00000000..4fe1d3ae --- /dev/null +++ b/app/presenters/analyze/graph/column/sped.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Analyze + module Graph + module Column + class Sped < ColumnBase + attr_reader :sped + + def initialize(sped:) + @sped = sped + end + + def label + ["#{sped.designation}"] + end + + def basis + "student surveys" + end + + def show_irrelevancy_message?(measure:) + false + end + + def show_insufficient_data_message?(measure:, school:, academic_years:) + false + end + + def type + :student + end + + def n_size(measure:, school:, academic_year:) + SurveyItemResponse.where(sped:, survey_item: measure.student_survey_items, school:, grade: grades(school:, academic_year:), + academic_year:).select(:response_id).distinct.count + end + + def score(measure:, school:, academic_year:) + meets_student_threshold = sufficient_student_responses?(measure:, school:, academic_year:) + return Score::NIL_SCORE unless meets_student_threshold + + averages = SurveyItemResponse.averages_for_sped(measure.student_survey_items, school, academic_year, + sped) + average = bubble_up_averages(measure:, averages:).round(2) + + Score.new(average:, + meets_teacher_threshold: false, + meets_student_threshold:, + meets_admin_data_threshold: false) + end + + def sufficient_student_responses?(measure:, school:, academic_year:) + return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? + + yearly_counts = SurveyItemResponse.where(school:, academic_year:, + sped:, survey_item: measure.student_survey_items).group(:sped).select(:response_id).distinct(:response_id).count + yearly_counts.any? do |count| + count[1] >= 10 + end + end + end + end + end +end diff --git a/app/presenters/analyze/graph/column/sped_column/not_sped.rb b/app/presenters/analyze/graph/column/sped_column/not_sped.rb deleted file mode 100644 index cd4ece24..00000000 --- a/app/presenters/analyze/graph/column/sped_column/not_sped.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module SpedColumn - class NotSped < GroupedBarColumnPresenter - include Analyze::Graph::Column::SpedColumn::ScoreForSped - include Analyze::Graph::Column::SpedColumn::SpedCount - - def label - ["Not Special", "Education"] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def sped - ::Sped.find_by_slug "not-special-education" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/sped_column/score_for_sped.rb b/app/presenters/analyze/graph/column/sped_column/score_for_sped.rb deleted file mode 100644 index 25831802..00000000 --- a/app/presenters/analyze/graph/column/sped_column/score_for_sped.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Analyze - module Graph - module Column - module SpedColumn - module ScoreForSped - def score(academic_year) - meets_student_threshold = sufficient_student_responses?(academic_year:) - return Score::NIL_SCORE unless meets_student_threshold - - averages = SurveyItemResponse.averages_for_sped(measure.student_survey_items, school, academic_year, - sped) - average = bubble_up_averages(averages:).round(2) - - Score.new(average:, - meets_teacher_threshold: false, - meets_student_threshold:, - meets_admin_data_threshold: false) - end - - def bubble_up_averages(averages:) - measure.student_scales.map do |scale| - scale.survey_items.map do |survey_item| - averages[survey_item] - 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:, - sped:, survey_item: measure.student_survey_items).group(:sped).select(:response_id).distinct(:response_id).count - yearly_counts.any? do |count| - count[1] >= 10 - end - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/sped_column/sped.rb b/app/presenters/analyze/graph/column/sped_column/sped.rb deleted file mode 100644 index 7e67e101..00000000 --- a/app/presenters/analyze/graph/column/sped_column/sped.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module SpedColumn - class Sped < GroupedBarColumnPresenter - include Analyze::Graph::Column::SpedColumn::ScoreForSped - include Analyze::Graph::Column::SpedColumn::SpedCount - - def label - %w[Special Education] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def sped - ::Sped.find_by_slug "special-education" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/sped_column/sped_count.rb b/app/presenters/analyze/graph/column/sped_column/sped_count.rb deleted file mode 100644 index eb88311a..00000000 --- a/app/presenters/analyze/graph/column/sped_column/sped_count.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Analyze - module Graph - module Column - module SpedColumn - module SpedCount - def type - :student - end - - def n_size(academic_year) - SurveyItemResponse.where(sped:, survey_item: measure.student_survey_items, school:, grade: grades, - academic_year:).select(:response_id).distinct.count - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/column/sped_column/unknown.rb b/app/presenters/analyze/graph/column/sped_column/unknown.rb deleted file mode 100644 index e3e7fa54..00000000 --- a/app/presenters/analyze/graph/column/sped_column/unknown.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module Analyze - module Graph - module Column - module SpedColumn - class Unknown < GroupedBarColumnPresenter - include Analyze::Graph::Column::SpedColumn::ScoreForSped - include Analyze::Graph::Column::SpedColumn::SpedCount - - def label - %w[Unknown] - end - - def basis - "student" - end - - def show_irrelevancy_message? - false - end - - def show_insufficient_data_message? - false - end - - def sped - ::Sped.find_by_slug "unknown" - end - end - end - end - end -end diff --git a/app/presenters/analyze/graph/students_and_teachers.rb b/app/presenters/analyze/graph/students_and_teachers.rb index 8d29538b..d1fb5ccc 100644 --- a/app/presenters/analyze/graph/students_and_teachers.rb +++ b/app/presenters/analyze/graph/students_and_teachers.rb @@ -13,7 +13,7 @@ module Analyze end def columns - [AllStudent, AllTeacher, AllSurveyData] + [AllStudent.new, AllTeacher.new, AllSurveyData.new] end def source diff --git a/app/presenters/analyze/graph/students_by_ell.rb b/app/presenters/analyze/graph/students_by_ell.rb index 1188d405..5ef3eee2 100644 --- a/app/presenters/analyze/graph/students_by_ell.rb +++ b/app/presenters/analyze/graph/students_by_ell.rb @@ -3,7 +3,6 @@ module Analyze module Graph class StudentsByEll - include Analyze::Graph::Column::EllColumn attr_reader :ells def initialize(ells:) @@ -21,10 +20,10 @@ module Analyze def columns [].tap do |array| ells.each do |ell| - array << column_for_ell_code(code: ell.slug) + array << Analyze::Graph::Column::Ell.new(ell:) end - array.sort_by!(&:to_s) - array << Analyze::Graph::Column::AllStudent + array.sort_by!(&:label) + array << Analyze::Graph::Column::AllStudent.new end end @@ -35,18 +34,6 @@ module Analyze def slice Analyze::Slice::StudentsByGroup.new end - - private - - def column_for_ell_code(code:) - CFR[code] - end - - CFR = { - "ell" => Analyze::Graph::Column::EllColumn::Ell, - "not-ell" => Analyze::Graph::Column::EllColumn::NotEll, - "unknown" => Analyze::Graph::Column::EllColumn::Unknown - }.freeze end end end diff --git a/app/presenters/analyze/graph/students_by_gender.rb b/app/presenters/analyze/graph/students_by_gender.rb index ccd1d2a5..333098c5 100644 --- a/app/presenters/analyze/graph/students_by_gender.rb +++ b/app/presenters/analyze/graph/students_by_gender.rb @@ -3,7 +3,6 @@ module Analyze module Graph class StudentsByGender - include Analyze::Graph::Column::GenderColumn attr_reader :genders def initialize(genders:) @@ -21,10 +20,10 @@ module Analyze def columns [].tap do |array| genders.each do |gender| - array << column_for_gender_code(code: gender.qualtrics_code) + array << Analyze::Graph::Column::Gender.new(gender:) end - array.sort_by!(&:to_s) - array << Analyze::Graph::Column::AllStudent + array.sort_by!(&:label) + array << Analyze::Graph::Column::AllStudent.new end end @@ -35,19 +34,6 @@ module Analyze def slice Analyze::Slice::StudentsByGroup.new end - - private - - def column_for_gender_code(code:) - CFR[code] - end - - CFR = { - 1 => Analyze::Graph::Column::GenderColumn::Female, - 2 => Analyze::Graph::Column::GenderColumn::Male, - 4 => Analyze::Graph::Column::GenderColumn::NonBinary, - 99 => Analyze::Graph::Column::GenderColumn::Unknown - }.freeze end end end diff --git a/app/presenters/analyze/graph/students_by_grade.rb b/app/presenters/analyze/graph/students_by_grade.rb index 1723e240..a28451e4 100644 --- a/app/presenters/analyze/graph/students_by_grade.rb +++ b/app/presenters/analyze/graph/students_by_grade.rb @@ -3,7 +3,6 @@ module Analyze module Graph class StudentsByGrade - include Analyze::Graph::Column::Grade attr_reader :grades def initialize(grades:) @@ -21,9 +20,9 @@ module Analyze def columns [].tap do |array| grades.each do |grade| - array << column_for_grade_code(code: grade) + array << Analyze::Graph::Column::Grade.new(grade: grade) end - array << Analyze::Graph::Column::AllStudent + array << Analyze::Graph::Column::AllStudent.new end end @@ -34,29 +33,6 @@ module Analyze def slice Analyze::Slice::StudentsByGroup.new end - - private - - def column_for_grade_code(code:) - CFR[code] - end - - CFR = { - -1 => PK, - 0 => Zero, - 1 => One, - 2 => Two, - 3 => Three, - 4 => Four, - 5 => Five, - 6 => Six, - 7 => Seven, - 8 => Eight, - 9 => Nine, - 10 => Ten, - 11 => Eleven, - 12 => Twelve - }.freeze end end end diff --git a/app/presenters/analyze/graph/students_by_income.rb b/app/presenters/analyze/graph/students_by_income.rb index d28be884..1f1b256d 100644 --- a/app/presenters/analyze/graph/students_by_income.rb +++ b/app/presenters/analyze/graph/students_by_income.rb @@ -20,9 +20,9 @@ module Analyze def columns [].tap do |array| incomes.each do |income| - array << column_for_income_code(code: income.slug) + array << Analyze::Graph::Column::Income.new(income:) end - array << Analyze::Graph::Column::AllStudent + array << Analyze::Graph::Column::AllStudent.new end end @@ -33,18 +33,6 @@ module Analyze def slice Analyze::Slice::StudentsByGroup.new end - - private - - def column_for_income_code(code:) - CFR[code.to_s] - end - - CFR = { - "economically-disadvantaged-y" => Analyze::Graph::Column::IncomeColumn::Disadvantaged, - "economically-disadvantaged-n" => Analyze::Graph::Column::IncomeColumn::NotDisadvantaged, - "unknown" => Analyze::Graph::Column::IncomeColumn::Unknown - }.freeze end end end diff --git a/app/presenters/analyze/graph/students_by_race.rb b/app/presenters/analyze/graph/students_by_race.rb index d3e3507c..740d4c09 100644 --- a/app/presenters/analyze/graph/students_by_race.rb +++ b/app/presenters/analyze/graph/students_by_race.rb @@ -20,9 +20,9 @@ module Analyze def columns [].tap do |array| races.each do |race| - array << column_for_race_code(code: race.qualtrics_code) + array << Analyze::Graph::Column::Race.new(race:) end - array << Analyze::Graph::Column::AllStudent + array << Analyze::Graph::Column::AllStudent.new end end @@ -33,23 +33,6 @@ module Analyze def slice Analyze::Slice::StudentsByGroup.new end - - private - - def column_for_race_code(code:) - CFR[code.to_s] - end - - CFR = { - "1" => Analyze::Graph::Column::RaceColumn::AmericanIndian, - "2" => Analyze::Graph::Column::RaceColumn::Asian, - "3" => Analyze::Graph::Column::RaceColumn::Black, - "4" => Analyze::Graph::Column::RaceColumn::Hispanic, - "5" => Analyze::Graph::Column::RaceColumn::White, - "8" => Analyze::Graph::Column::RaceColumn::MiddleEastern, - "99" => Analyze::Graph::Column::RaceColumn::Unknown, - "100" => Analyze::Graph::Column::RaceColumn::Multiracial - }.freeze end end end diff --git a/app/presenters/analyze/graph/students_by_sped.rb b/app/presenters/analyze/graph/students_by_sped.rb index bc5c4289..d6afe386 100644 --- a/app/presenters/analyze/graph/students_by_sped.rb +++ b/app/presenters/analyze/graph/students_by_sped.rb @@ -3,7 +3,6 @@ module Analyze module Graph class StudentsBySped - include Analyze::Graph::Column::SpedColumn attr_reader :speds def initialize(speds:) @@ -21,9 +20,9 @@ module Analyze def columns [].tap do |array| speds.each do |sped| - array << column_for_sped_code(code: sped.slug) + array << Analyze::Graph::Column::Sped.new(sped:) end - array << Analyze::Graph::Column::AllStudent + array << Analyze::Graph::Column::AllStudent.new end end @@ -34,18 +33,6 @@ module Analyze def slice Analyze::Slice::StudentsByGroup.new end - - private - - def column_for_sped_code(code:) - CFR[code] - end - - CFR = { - "special-education" => Analyze::Graph::Column::SpedColumn::Sped, - "not-special-education" => Analyze::Graph::Column::SpedColumn::NotSped, - "unknown" => Analyze::Graph::Column::SpedColumn::Unknown - }.freeze end end end diff --git a/app/presenters/analyze/presenter.rb b/app/presenters/analyze/presenter.rb index d67d51c1..2d796c19 100644 --- a/app/presenters/analyze/presenter.rb +++ b/app/presenters/analyze/presenter.rb @@ -118,6 +118,20 @@ module Analyze @source ||= graph&.source || sources.first end + def show_secondary_graph?(measure:) + return false unless measure.includes_parent_survey_items? + + graph.slug == "all-data" + end + + def columns_for_measure(measure:) + return unless measure.includes_parent_survey_items? + + measure.scales.parent_scales.map do |scale| + Analyze::Graph::Column::Parent::Scale.new(scale:) + end + end + def sources all_data_slice = Analyze::Slice::AllData.new all_data_slice.graph = Analyze::Graph::AllData.new diff --git a/app/views/analyze/_grouped_bar_chart.html.erb b/app/views/analyze/_grouped_bar_chart.html.erb index 944cde5a..ec5c4792 100644 --- a/app/views/analyze/_grouped_bar_chart.html.erb +++ b/app/views/analyze/_grouped_bar_chart.html.erb @@ -1,9 +1,9 @@ <%= render partial: "graph_background", locals: {background: @background} %> - <% number_of_columns = @presenter.graph.columns.length %> - <% @presenter.graph.columns.each_with_index do |column, index| %> - <% p = column.new(measure: measure, school: @school, academic_years: @presenter.selected_academic_years, position: index , number_of_columns:) %> + <% number_of_columns = columns.length %> + <% columns.each_with_index do |config, index| %> + <% p = Analyze::Graph::Column::GroupedBarColumnPresenter.new(measure: measure, school: @school, academic_years: @presenter.selected_academic_years, position: index , number_of_columns:, config: config) %> <%= render partial: "grouped_bar_column", locals: {column: p} %> <% end %> diff --git a/app/views/analyze/index.html.erb b/app/views/analyze/index.html.erb index 289e5e48..ba623754 100644 --- a/app/views/analyze/index.html.erb +++ b/app/views/analyze/index.html.erb @@ -1,5 +1,5 @@ <%= turbo_frame_tag "results" do %> - + <% content_for :title do %>

Analysis of <%= @school.name %>

<% end %> @@ -11,18 +11,28 @@
- <%= render partial: "focus_area", locals: {categories: @presenter.categories, district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategories: @presenter.subcategories} %> - <%= render partial: "school_years", locals: {available_academic_years: @presenter.academic_years, selected_academic_years: @presenter.selected_academic_years, district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategory: @presenter.subcategory, measures: @presenter.measures, graph: @presenter.graph} %> - <%= render partial: "data_filters", locals: {district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategory: @presenter.subcategory} %> + <%= render partial: "focus_area", locals: {categories: @presenter.categories, district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategories: @presenter.subcategories} %> + <%= render partial: "school_years", locals: {available_academic_years: @presenter.academic_years, selected_academic_years: @presenter.selected_academic_years, district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategory: @presenter.subcategory, measures: @presenter.measures, graph: @presenter.graph} %> + <%= render partial: "data_filters", locals: {district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategory: @presenter.subcategory} %>
<% cache [@school, @presenter.cache_objects] do %>
+ <% @presenter.measures.each do |measure| %>
<%= link_to("MEASURE " + measure.measure_id.upcase, district_school_category_path( @district, @school, @presenter.category, {year: @presenter.selected_academic_years&.last&.range , anchor: "#{measure.measure_id}"}), class: "construct-id", data: {turbo_frame: "_top"}) %>

<%= measure.name %>

- <%= render partial: "grouped_bar_chart" , locals: { measure: measure} %> + <%= render partial: "grouped_bar_chart" , locals: { measure: measure, columns: @presenter.graph.columns} %>
+ + <% if @presenter.show_secondary_graph?(measure:) %> +
+ <%= link_to("Parent Survey", district_school_category_path( @district, @school, @presenter.category, {year: @presenter.selected_academic_years&.last&.range , anchor: "#{measure.measure_id}"}), class: "construct-id", data: {turbo_frame: "_top"}) %> +

<%= measure.subcategory.name %>

+ <%= render partial: "grouped_bar_chart" , locals: { measure: measure, columns: @presenter.columns_for_measure(measure:)} %> +
+ <% end %> + <% end %>
<% end %> diff --git a/spec/models/analyze/graph/column/GenderColumn/unknown_spec.rb b/spec/models/analyze/graph/column/GenderColumn/unknown_spec.rb deleted file mode 100644 index 0877c603..00000000 --- a/spec/models/analyze/graph/column/GenderColumn/unknown_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -require "rails_helper" - -RSpec.describe Analyze::Graph::Column::GenderColumn::Unknown, type: :model do - let(:school) { create(:school) } - let(:academic_year) { create(:academic_year) } - let(:measure) { create(:measure) } - let(:academic_years) { [academic_year] } - let(:position) { 0 } - let(:number_of_columns) { 1 } - let(:gender) { create(:gender, qualtrics_code: 99) } - - let(:subcategory) { create(:subcategory, subcategory_id: "1A") } - let(:measure) { create(:measure, measure_id: "1A-iii", subcategory:) } - let(:scale) { create(:student_scale, measure:) } - let(:survey_item) { create(:student_survey_item, scale:) } - let(:teacher_scale) { create(:teacher_scale, measure:) } - let(:teacher_survey_item) { create(:teacher_survey_item, scale:) } - - context "when no teacher responses exist" do - context "when there are insufficient unknown students" do - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(nil) - end - it "reports insufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(false) - end - end - context "when there are sufficient unknown students" do - before :each do - create_list(:survey_item_response, 10, school:, academic_year:, gender:, survey_item:) - end - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(3) - end - - it "reports sufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(true) - end - end - end - - context "when teacher responses exist" do - before :each do - create_list(:survey_item_response, 10, school:, academic_year:, survey_item: teacher_survey_item, likert_score: 5) - end - - context "when there are insufficient unknown students" do - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(nil) - end - it "reports insufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(false) - end - end - context "when there are sufficient unknown students" do - before :each do - create_list(:survey_item_response, 10, school:, academic_year:, gender:, survey_item:) - end - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(3) - end - - it "reports sufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(true) - end - end - end -end - diff --git a/spec/models/analyze/graph/column/gender.rb b/spec/models/analyze/graph/column/gender.rb new file mode 100644 index 00000000..f0a7453c --- /dev/null +++ b/spec/models/analyze/graph/column/gender.rb @@ -0,0 +1,74 @@ +require "rails_helper" +include Analyze::Graph::Column + +RSpec.describe Gender, type: :model do + let(:school) { create(:school) } + let(:academic_year) { create(:academic_year) } + let(:measure) { create(:measure) } + let(:academic_years) { [academic_year] } + let(:position) { 0 } + let(:number_of_columns) { 1 } + let(:gender) { create(:gender, qualtrics_code: 99) } + + let(:subcategory) { create(:subcategory, subcategory_id: "1A") } + let(:measure) { create(:measure, measure_id: "1A-iii", subcategory:) } + let(:scale) { create(:student_scale, measure:) } + let(:survey_item) { create(:student_survey_item, scale:) } + let(:teacher_scale) { create(:teacher_scale, measure:) } + let(:teacher_survey_item) { create(:teacher_survey_item, scale:) } + let(:config) { Analyze::Graph::Column::Gender.new(gender: ::Gender.find_by_qualtrics_code(99)) } + + context "when no teacher responses exist" do + context "when there are insufficient unknown students" do + it "reports a score of 3 when the average is 3" do + expect(GroupedBarColumnPresenter.new(school:, academic_years:, position:, measure:, + number_of_columns:, config:).score(academic_year:).average).to eq(nil) + end + it "reports insufficient data" do + expect(config.sufficient_student_responses?(measure:, school:, academic_year:)).to eq(false) + end + end + context "when there are sufficient unknown students" do + before :each do + create_list(:survey_item_response, 10, school:, academic_year:, gender:, survey_item:) + end + it "reports a score of 3 when the average is 3" do + expect(GroupedBarColumnPresenter.new(school:, academic_years:, position:, measure:, + number_of_columns:, config:).score(academic_year:).average).to eq(3) + end + + it "reports sufficient data" do + expect(config.sufficient_student_responses?(measure:, school:, academic_year:)).to eq(true) + end + end + end + + context "when teacher responses exist" do + before :each do + create_list(:survey_item_response, 10, school:, academic_year:, survey_item: teacher_survey_item, likert_score: 5) + end + + context "when there are insufficient unknown students" do + it "reports a score of 3 when the average is 3" do + expect(GroupedBarColumnPresenter.new(school:, academic_years:, position:, measure:, + number_of_columns:, config:).score(academic_year:).average).to eq(nil) + end + it "reports insufficient data" do + expect(config.sufficient_student_responses?(measure:, school:, academic_year:)).to eq(false) + end + end + context "when there are sufficient unknown students" do + before :each do + create_list(:survey_item_response, 10, school:, academic_year:, gender:, survey_item:) + end + it "reports a score of 3 when the average is 3" do + expect(GroupedBarColumnPresenter.new(school:, academic_years:, position:, measure:, + number_of_columns:, config:).score(academic_year:).average).to eq(3) + end + + it "reports sufficient data" do + expect(config.sufficient_student_responses?(measure:, school:, academic_year:)).to eq(true) + end + end + end +end diff --git a/spec/models/analyze/graph/column/gender_column/unknown_spec.rb b/spec/models/analyze/graph/column/gender_column/unknown_spec.rb deleted file mode 100644 index defb9d01..00000000 --- a/spec/models/analyze/graph/column/gender_column/unknown_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -require "rails_helper" - -RSpec.describe Analyze::Graph::Column::GenderColumn::Unknown, type: :model do - let(:school) { create(:school) } - let(:academic_year) { create(:academic_year) } - let(:measure) { create(:measure) } - let(:academic_years) { [academic_year] } - let(:position) { 0 } - let(:number_of_columns) { 1 } - let(:gender) { create(:gender, qualtrics_code: 99) } - - let(:subcategory) { create(:subcategory, subcategory_id: "1A") } - let(:measure) { create(:measure, measure_id: "1A-iii", subcategory:) } - let(:scale) { create(:student_scale, measure:) } - let(:survey_item) { create(:student_survey_item, scale:) } - let(:teacher_scale) { create(:teacher_scale, measure:) } - let(:teacher_survey_item) { create(:teacher_survey_item, scale:) } - - context "when no teacher responses exist" do - context "when there are insufficient unknown students" do - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(nil) - end - it "reports insufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(false) - end - end - context "when there are sufficient unknown students" do - before :each do - create_list(:survey_item_response, 10, school:, academic_year:, gender:, survey_item:) - end - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(3) - end - - it "reports sufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(true) - end - end - end - - context "when teacher responses exist" do - before :each do - create_list(:survey_item_response, 10, school:, academic_year:, survey_item: teacher_survey_item, likert_score: 5) - end - - context "when there are insufficient unknown students" do - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(nil) - end - it "reports insufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(false) - end - end - context "when there are sufficient unknown students" do - before :each do - create_list(:survey_item_response, 10, school:, academic_year:, gender:, survey_item:) - end - it "reports a score of 3 when the average is 3" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).score(academic_year).average).to eq(3) - end - - it "reports sufficient data" do - expect(Analyze::Graph::Column::GenderColumn::Unknown.new(school:, academic_years:, position:, measure:, - number_of_columns:).sufficient_student_responses?(academic_year:)).to eq(true) - end - end - end -end diff --git a/spec/presenters/analyze/graph/column/all_admin_spec.rb b/spec/presenters/analyze/graph/column/all_admin_spec.rb deleted file mode 100644 index 7c7df87a..00000000 --- a/spec/presenters/analyze/graph/column/all_admin_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'rails_helper' -include Analyze::Graph::Column - -describe AllAdmin do - let(:measure_without_admin) { create(:measure) } - let(:measure_with_admin) { create(:measure, :with_admin_data_items) } - let(:school) { create(:school) } - let(:academic_years) { [create(:academic_year)] } - let(:position) { 1 } - let(:number_of_columns) { 1 } - - context '.show_irrelevancy_message?' do - it 'returns true when the measure does NOT include admin data items' do - expect(AllAdmin.new(measure: measure_without_admin, school:, academic_years:, position:, - number_of_columns:).show_irrelevancy_message?).to eq true - end - - it 'returns false when the measure includes admin data items' do - expect(AllAdmin.new(measure: measure_with_admin, school:, academic_years:, position:, - number_of_columns:).show_irrelevancy_message?).to eq false - end - end - - context '.show_insufficient_data_message?' do - context 'when the measure DOES NOT include admin data items' do - it 'returns true ' do - expect(AllAdmin.new(measure: measure_without_admin, school:, academic_years:, position:, - number_of_columns:).show_insufficient_data_message?).to eq true - end - - it 'returns true when the measure does include admin data items but there are not values assigned to the admin' do - expect(AllAdmin.new(measure: measure_with_admin, school:, academic_years:, position:, - number_of_columns:).show_insufficient_data_message?).to eq true - end - end - - context 'when the measure Does include admin data items' do - it 'and has at least one value to show, it will return false' do - admin_data_item = measure_with_admin.scales.first.admin_data_items.first - create(:admin_data_value, admin_data_item:, school:, academic_year: academic_years.first) - - expect(AllAdmin.new(measure: measure_with_admin, school:, academic_years:, position:, - number_of_columns:).show_insufficient_data_message?).to eq false - end - end - end -end diff --git a/spec/presenters/analyze/graph/column/gender/female_spec.rb b/spec/presenters/analyze/graph/column/gender/female_spec.rb deleted file mode 100644 index a9dd8eed..00000000 --- a/spec/presenters/analyze/graph/column/gender/female_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'rails_helper' -include Analyze::Graph -include Analyze::Graph::Column::GenderColumn -describe StudentsByRace do - let(:female) { create(:gender, qualtrics_code: 1, designation: 'Female') } - let(:school) { create(:school) } - let(:academic_year) { create(:academic_year, range: '1900-01') } - let(:academic_years) { [academic_year] } - let(:year_index) { academic_years.find_index(academic_year) } - - let(:measure_with_student_survey_items) { create(:measure, name: 'Student measure') } - let(:scale_with_student_survey_item) { create(:student_scale, measure: measure_with_student_survey_items) } - let(:student_survey_item) do - create(:student_survey_item, scale: scale_with_student_survey_item) - end - - before do - create_list(:survey_item_response, 1, survey_item: student_survey_item, school:, academic_year:, gender: female) - end - - context '.gender' do - it 'returns female gender' do - expect(Female.new(measure: measure_with_student_survey_items, school:, academic_years:, position: year_index, - number_of_columns: 1).gender).to eq female - end - - it 'returns the count of survey items for females for that school and academic_year ' do - female_column = Female.new(measure: measure_with_student_survey_items, school:, academic_years:, position: year_index, - number_of_columns: 1) - expect(female_column.sufficient_student_responses?(academic_year:)).to eq false - end - - context 'when there are more than 10 students who responded' do - before do - create_list(:survey_item_response, 10, survey_item: student_survey_item, school:, academic_year:, - gender: female) - end - it 'returns the count of survey items for females for that school and academic_year ' do - female_column = Female.new(measure: measure_with_student_survey_items, school:, academic_years:, position: year_index, - number_of_columns: 1) - expect(female_column.sufficient_student_responses?(academic_year:)).to eq true - end - end - end -end diff --git a/spec/presenters/analyze/graph/students_by_race_spec.rb b/spec/presenters/analyze/graph/students_by_race_spec.rb index 5f78582c..978a19ec 100644 --- a/spec/presenters/analyze/graph/students_by_race_spec.rb +++ b/spec/presenters/analyze/graph/students_by_race_spec.rb @@ -1,23 +1,23 @@ require 'rails_helper' include Analyze::Graph include Analyze::Graph::Column -include Analyze::Graph::Column::RaceColumn + describe StudentsByRace do - let(:american_indian) { create(:race, qualtrics_code: 1) } - let(:asian) { create(:race, qualtrics_code: 2) } - let(:black) { create(:race, qualtrics_code: 3) } - let(:hispanic) { create(:race, qualtrics_code: 4) } - let(:white) { create(:race, qualtrics_code: 5) } - let(:unknown) { create(:race, qualtrics_code: 99) } - let(:multiracial) { create(:race, qualtrics_code: 100) } + let(:american_indian) { create(:race, designation: "american indian", qualtrics_code: 1) } + let(:asian) { create(:race, designation: "asian", qualtrics_code: 2) } + let(:black) { create(:race, designation: "black", qualtrics_code: 3) } + let(:hispanic) { create(:race, designation: "hispanic", qualtrics_code: 4) } + let(:white) { create(:race, designation: "white", qualtrics_code: 5) } + let(:unknown) { create(:race, designation: "unknown", qualtrics_code: 99) } + let(:multiracial) { create(:race, designation: "multiracial", qualtrics_code: 100) } context 'when initialized with a list of races' do it 'generates corresponding race columns' do races = [american_indian] - expect(StudentsByRace.new(races:).columns).to eq [AmericanIndian, AllStudent] + expect(StudentsByRace.new(races:).columns.map(&:label).map { |words| words.join(" ") }).to eq ["american indian", "All Students"] races = [american_indian, asian] - expect(StudentsByRace.new(races:).columns).to eq [AmericanIndian, Asian, AllStudent] + expect(StudentsByRace.new(races:).columns.map(&:label).map { |words| words.join(" ") }).to eq ["american indian", "asian", "All Students"] races = [black, hispanic, multiracial] - expect(StudentsByRace.new(races:).columns).to eq [Black, Hispanic, Multiracial, AllStudent] + expect(StudentsByRace.new(races:).columns.map(&:label).map { |words| words.join(" ") }).to eq ["black", "hispanic", "multiracial", "All Students"] end end end diff --git a/spec/presenters/grouped_bar_column_presenter_spec.rb b/spec/presenters/grouped_bar_column_presenter_spec.rb index 194e1218..6b8818a8 100644 --- a/spec/presenters/grouped_bar_column_presenter_spec.rb +++ b/spec/presenters/grouped_bar_column_presenter_spec.rb @@ -63,18 +63,18 @@ describe GroupedBarColumnPresenter do end let(:student_presenter) do - Analyze::Graph::Column::AllStudent.new measure: measure_with_student_survey_items, school:, academic_years:, - position: 0, number_of_columns: 3 + GroupedBarColumnPresenter.new measure: measure_with_student_survey_items, school:, academic_years:, + position: 0, number_of_columns: 3, config: Analyze::Graph::Column::AllStudent.new end let(:teacher_presenter) do - Analyze::Graph::Column::AllTeacher.new measure: measure_with_teacher_survey_items, school:, academic_years:, - position: 0, number_of_columns: 3 + GroupedBarColumnPresenter.new measure: measure_with_teacher_survey_items, school:, academic_years:, + position: 0, number_of_columns: 3, config: Analyze::Graph::Column::AllTeacher.new end let(:all_data_presenter) do - Analyze::Graph::Column::AllData.new measure: measure_composed_of_student_and_teacher_items, school:, academic_years:, - position: 0, number_of_columns: 3 + GroupedBarColumnPresenter.new measure: measure_composed_of_student_and_teacher_items, school:, academic_years:, + position: 0, number_of_columns: 3, config: Analyze::Graph::Column::AllData.new end before do @@ -120,8 +120,8 @@ describe GroupedBarColumnPresenter do end it "returns a score that is an average of the likert scores " do - expect(all_data_presenter.score(academic_year).average).to eq 4.5 - expect(all_data_presenter.score(another_academic_year).average).to eq nil + expect(all_data_presenter.score(academic_year:).average).to eq 4.5 + expect(all_data_presenter.score(academic_year: another_academic_year).average).to eq nil expect(all_data_presenter.academic_years[0].range).to be academic_year.range expect(all_data_presenter.academic_years[1].range).to be another_academic_year.range end @@ -133,8 +133,8 @@ describe GroupedBarColumnPresenter do academic_year: another_academic_year, likert_score: 3) end it "returns independent scores for each year of data" do - expect(all_data_presenter.score(academic_year).average).to eq 4.5 - expect(all_data_presenter.score(another_academic_year).average).to eq 4 + expect(all_data_presenter.score(academic_year:).average).to eq 4.5 + expect(all_data_presenter.score(academic_year: another_academic_year).average).to eq 4 end end end @@ -145,7 +145,7 @@ describe GroupedBarColumnPresenter do it_behaves_like "column_midpoint" it "returns an emty score" do - expect(student_presenter.score(academic_year).average).to eq nil + expect(student_presenter.score(academic_year:).average).to eq nil end it "shows the irrelevancy message " do