Refactor GroupedBarColumnPresenter to accept a configuration so that a

column can by given on the fly (dependency injection). Show Parent
graphs on analyze page.
mciea-main
rebuilt 10 months ago
parent c30e2b3f6f
commit 9911a75dc8

@ -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:)

@ -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

@ -5,6 +5,10 @@ module Analyze
class AllData
include Analyze::Graph::Column
def label
["All", "Data"]
end
def to_s
"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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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)]

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -13,7 +13,7 @@ module Analyze
end
def columns
[AllStudent, AllTeacher, AllSurveyData]
[AllStudent.new, AllTeacher.new, AllSurveyData.new]
end
def source

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -1,9 +1,9 @@
<svg width="100%" height="<%= svg_height %>">
<%= 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 %>
</svg>

Before

Width:  |  Height:  |  Size: 492 B

After

Width:  |  Height:  |  Size: 517 B

@ -1,5 +1,5 @@
<%= turbo_frame_tag "results" do %>
<meta name="turbo-visit-control" content="reload">
<meta name="turbo-visit-control" content="reload">
<% content_for :title do %>
<h1 class="sub-header-2 color-white m-0"> Analysis of <%= @school.name %> </h1>
<% end %>
@ -11,18 +11,28 @@
</div>
<div class="d-flex flex-row pt-5 row">
<div class="d-flex flex-column flex-grow-6 bg-color-white col-3 px-5" >
<%= 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} %>
</div>
<% cache [@school, @presenter.cache_objects] do %>
<div class="bg-color-white flex-grow-1 col-9">
<% @presenter.measures.each do |measure| %>
<section class="mb-6">
<%= 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"}) %>
<h2> <%= measure.name %> </h2>
<%= render partial: "grouped_bar_chart" , locals: { measure: measure} %>
<%= render partial: "grouped_bar_chart" , locals: { measure: measure, columns: @presenter.graph.columns} %>
</section>
<% if @presenter.show_secondary_graph?(measure:) %>
<section class="mb-6">
<%= 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"}) %>
<h2> <%= measure.subcategory.name %> </h2>
<%= render partial: "grouped_bar_chart" , locals: { measure: measure, columns: @presenter.columns_for_measure(measure:)} %>
</section>
<% end %>
<% end %>
</div>
<% end %>

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

Loading…
Cancel
Save