mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-08 23:18:18 -07:00
Add scales to framework. Change calculations to first group and then
average those groupings and the way up the framework. Likert scores for a survey_item are averaged. Then all the survey_items in a scale are averaged. Then student scales in a measure are averaged. And teacher scales in a measure are averaged. Then the average of those two calculations becomes the score for a measure. Then the measures in a subcategory are averaged.
This commit is contained in:
parent
1ca88bf6d1
commit
d4df7cbc06
44 changed files with 1053 additions and 856 deletions
|
|
@ -7,7 +7,7 @@ class OverviewController < SqmApplicationController
|
|||
private
|
||||
|
||||
def presenter_for_measure(measure)
|
||||
score = SurveyItemResponse.score_for_measure(measure: measure, school: @school, academic_year: @academic_year)
|
||||
score = measure.score(school: @school, academic_year: @academic_year)
|
||||
|
||||
VarianceChartRowPresenter.new(measure: measure, score: score)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class SqmApplicationController < ApplicationController
|
|||
@schools = School.includes([:district]).where(district: @district).order(:name)
|
||||
@academic_year = AcademicYear.find_by_range params[:year]
|
||||
@academic_years = AcademicYear.all.order(range: :desc)
|
||||
@has_empty_dataset = Measure.none_meet_threshold? school: @school, academic_year: @academic_year
|
||||
@has_empty_dataset = Measure.all.all? do |measure| measure.none_meet_threshold? school: @school, academic_year: @academic_year end
|
||||
end
|
||||
|
||||
def district_slug
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ require 'csv'
|
|||
class Seeder
|
||||
def seed_academic_years(*academic_year_ranges)
|
||||
academic_year_ranges.each do |range|
|
||||
AcademicYear.find_or_create_by! range: range
|
||||
AcademicYear.find_or_create_by! range:
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -89,8 +89,11 @@ class Seeder
|
|||
measure.save!
|
||||
|
||||
data_item_id = row['Survey Item ID'].strip
|
||||
scale_id = data_item_id.split('-')[0..1].join('-')
|
||||
scale = Scale.find_or_create_by! scale_id: scale_id, measure: measure
|
||||
|
||||
if %w[Teachers Students].include? row['Source']
|
||||
survey_item = SurveyItem.find_or_create_by! survey_item_id: data_item_id, measure: measure
|
||||
survey_item = SurveyItem.where(survey_item_id: data_item_id, scale:).first_or_create
|
||||
survey_item.watch_low_benchmark = watch_low if watch_low
|
||||
survey_item.growth_low_benchmark = growth_low if growth_low
|
||||
survey_item.approval_low_benchmark = approval_low if approval_low
|
||||
|
|
@ -99,7 +102,7 @@ class Seeder
|
|||
end
|
||||
|
||||
if row['Source'] == 'Admin Data'
|
||||
admin_data_item = AdminDataItem.find_or_create_by! admin_data_item_id: data_item_id, measure: measure
|
||||
admin_data_item = AdminDataItem.where(admin_data_item_id: data_item_id, scale:).first_or_create
|
||||
admin_data_item.watch_low_benchmark = watch_low if watch_low
|
||||
admin_data_item.growth_low_benchmark = growth_low if growth_low
|
||||
admin_data_item.approval_low_benchmark = approval_low if approval_low
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
class AdminDataItem < ActiveRecord::Base
|
||||
belongs_to :measure
|
||||
belongs_to :scale
|
||||
|
||||
scope :for_measures, ->(measure) {
|
||||
joins(:measure).where('admin_data_items.measure': measure)
|
||||
scope :for_measures, lambda { |measures|
|
||||
joins(:scale).where('scale.measure': measures)
|
||||
}
|
||||
|
||||
scope :non_hs_items_for_measures, ->(measure) {
|
||||
scope :non_hs_items_for_measures, lambda { |measure|
|
||||
for_measures(measure).where(hs_only_item: false)
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,34 +1,40 @@
|
|||
class Measure < ActiveRecord::Base
|
||||
belongs_to :subcategory
|
||||
has_many :survey_items
|
||||
has_many :admin_data_items
|
||||
|
||||
has_many :scales
|
||||
has_many :admin_data_items, through: :scales
|
||||
has_many :survey_items, through: :scales
|
||||
has_many :survey_item_responses, through: :survey_items
|
||||
|
||||
def self.none_meet_threshold?(school:, academic_year:)
|
||||
none? do |measure|
|
||||
SurveyItemResponse.sufficient_data?(measure: measure, school: school, academic_year: academic_year)
|
||||
end
|
||||
def none_meet_threshold?(school:, academic_year:)
|
||||
!sufficient_data?(school:, academic_year:)
|
||||
end
|
||||
|
||||
def teacher_survey_items
|
||||
@teacher_survey_items ||= survey_items.where("survey_item_id LIKE 't-%'")
|
||||
@teacher_survey_items ||= survey_items.teacher_survey_items
|
||||
end
|
||||
|
||||
def student_survey_items
|
||||
@student_survey_items ||= survey_items.where("survey_item_id LIKE 's-%'")
|
||||
@student_survey_items ||= survey_items.student_survey_items
|
||||
end
|
||||
|
||||
def teacher_scales
|
||||
@teacher_scales ||= scales.teacher_scales
|
||||
end
|
||||
|
||||
def student_scales
|
||||
@student_scales ||= scales.student_scales
|
||||
end
|
||||
|
||||
def includes_teacher_survey_items?
|
||||
@includes_teacher_survey_items ||= teacher_survey_items.any?
|
||||
teacher_survey_items.any?
|
||||
end
|
||||
|
||||
def includes_student_survey_items?
|
||||
@includes_student_survey_items ||= student_survey_items.any?
|
||||
student_survey_items.any?
|
||||
end
|
||||
|
||||
def includes_admin_data_items?
|
||||
@includes_admin_data_items ||= admin_data_items.any?
|
||||
admin_data_items.any?
|
||||
end
|
||||
|
||||
def sources
|
||||
|
|
@ -39,32 +45,61 @@ class Measure < ActiveRecord::Base
|
|||
sources
|
||||
end
|
||||
|
||||
def score(school:, academic_year:)
|
||||
@score ||= Hash.new do |memo|
|
||||
meets_student_threshold = sufficient_student_data?(school:, academic_year:)
|
||||
meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:)
|
||||
next Score.new(nil, false, false) if !meets_student_threshold && !meets_teacher_threshold
|
||||
|
||||
scores = []
|
||||
scores << teacher_scales.map { |scale| scale.score(school:, academic_year:) }.average if meets_teacher_threshold
|
||||
scores << student_scales.map { |scale| scale.score(school:, academic_year:) }.average if meets_student_threshold
|
||||
memo[[school, academic_year]] = Score.new(scores.average, meets_teacher_threshold, meets_student_threshold)
|
||||
end
|
||||
|
||||
@score[[school, academic_year]]
|
||||
end
|
||||
|
||||
def warning_low_benchmark
|
||||
1
|
||||
end
|
||||
|
||||
def watch_low_benchmark
|
||||
return @watch_low_benchmark unless @watch_low_benchmark.nil?
|
||||
|
||||
@watch_low_benchmark = benchmark(:watch_low_benchmark)
|
||||
@watch_low_benchmark ||= benchmark(:watch_low_benchmark)
|
||||
end
|
||||
|
||||
def growth_low_benchmark
|
||||
return @growth_low_benchmark unless @growth_low_benchmark.nil?
|
||||
|
||||
@growth_low_benchmark = benchmark(:growth_low_benchmark)
|
||||
@growth_low_benchmark ||= benchmark(:growth_low_benchmark)
|
||||
end
|
||||
|
||||
def approval_low_benchmark
|
||||
return @approval_low_benchmark unless @approval_low_benchmark.nil?
|
||||
|
||||
@approval_low_benchmark = benchmark(:approval_low_benchmark)
|
||||
@approval_low_benchmark ||= benchmark(:approval_low_benchmark)
|
||||
end
|
||||
|
||||
def ideal_low_benchmark
|
||||
return @ideal_low_benchmark unless @ideal_low_benchmark.nil?
|
||||
@ideal_low_benchmark ||= benchmark(:ideal_low_benchmark)
|
||||
end
|
||||
|
||||
@ideal_low_benchmark = benchmark(:ideal_low_benchmark)
|
||||
def sufficient_student_data?(school:, academic_year:)
|
||||
return false unless includes_student_survey_items?
|
||||
|
||||
average_response_count = student_survey_items.map do |survey_item|
|
||||
survey_item.survey_item_responses.where(school:, academic_year:).count
|
||||
end.average
|
||||
average_response_count >= SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD
|
||||
end
|
||||
|
||||
def sufficient_teacher_data?(school:, academic_year:)
|
||||
return false unless includes_teacher_survey_items?
|
||||
|
||||
average_response_count = teacher_survey_items.map do |survey_item|
|
||||
survey_item.survey_item_responses.where(school:, academic_year:).count
|
||||
end.average
|
||||
average_response_count >= SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD
|
||||
end
|
||||
|
||||
def sufficient_data?(school:, academic_year:)
|
||||
sufficient_student_data?(school:, academic_year:) || sufficient_teacher_data?(school:, academic_year:)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
class ResponseRate
|
||||
module ResponseRate
|
||||
def initialize(subcategory:, school:, academic_year:)
|
||||
@subcategory = subcategory
|
||||
@school = school
|
||||
|
|
|
|||
21
app/models/scale.rb
Normal file
21
app/models/scale.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
class Scale < ApplicationRecord
|
||||
belongs_to :measure
|
||||
has_many :survey_items
|
||||
has_many :admin_data_items
|
||||
|
||||
def score(school:, academic_year:)
|
||||
@score ||= Hash.new do |memo|
|
||||
memo[[school, academic_year]] = survey_items.map do |survey_item|
|
||||
survey_item.score(school:, academic_year:)
|
||||
end.average
|
||||
end
|
||||
@score[[school, academic_year]]
|
||||
end
|
||||
|
||||
scope :teacher_scales, lambda {
|
||||
where("scale_id LIKE 't-%'")
|
||||
}
|
||||
scope :student_scales, lambda {
|
||||
where("scale_id LIKE 's-%'")
|
||||
}
|
||||
end
|
||||
|
|
@ -1,17 +1,18 @@
|
|||
class StudentResponseRate < ResponseRate
|
||||
def rate
|
||||
super
|
||||
end
|
||||
class StudentResponseRate
|
||||
include ResponseRate
|
||||
|
||||
private
|
||||
|
||||
def survey_item_count
|
||||
@student_survey_item_count ||= SurveyItem.student_survey_items_for_measures(@subcategory.measures).count
|
||||
@student_survey_item_count ||= @subcategory.measures.map { |measure| measure.student_survey_items.count }.sum
|
||||
end
|
||||
|
||||
def response_count
|
||||
@student_response_count ||= SurveyItemResponse.student_responses_for_measures(@subcategory.measures, @school,
|
||||
@academic_year).count
|
||||
@student_response_count ||= @subcategory.measures.map do |measure|
|
||||
measure.student_survey_items.map do |survey_item|
|
||||
survey_item.survey_item_responses.where(school: @school, academic_year: @academic_year).count
|
||||
end.sum
|
||||
end.sum
|
||||
end
|
||||
|
||||
def total_possible_responses
|
||||
|
|
|
|||
|
|
@ -2,4 +2,12 @@ class Subcategory < ActiveRecord::Base
|
|||
belongs_to :category
|
||||
|
||||
has_many :measures
|
||||
|
||||
def score(school:, academic_year:)
|
||||
scores = measures.includes([:survey_items]).map do |measure|
|
||||
measure.score(school:, academic_year:).average
|
||||
end
|
||||
scores = scores.reject(&:nil?)
|
||||
scores.average
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,21 @@
|
|||
class SurveyItem < ActiveRecord::Base
|
||||
belongs_to :measure
|
||||
belongs_to :scale
|
||||
has_one :measure, through: :scale
|
||||
|
||||
has_many :survey_item_responses
|
||||
|
||||
scope :student_survey_items_for_measures, lambda { |measures|
|
||||
joins(:measure).where(measure: measures).where("survey_item_id LIKE 's-%'")
|
||||
def score(school:, academic_year:)
|
||||
@score ||= Hash.new do |memo|
|
||||
memo[[school, academic_year]] = survey_item_responses.where(school:, academic_year:).average(:likert_score).to_f
|
||||
end
|
||||
|
||||
@score[[school, academic_year]]
|
||||
end
|
||||
|
||||
scope :student_survey_items, lambda {
|
||||
where("survey_item_id LIKE 's-%'")
|
||||
}
|
||||
scope :teacher_survey_items_for_measures, lambda { |measures|
|
||||
joins(:measure).where(measure: measures).where("survey_item_id LIKE 't-%'")
|
||||
scope :teacher_survey_items, lambda {
|
||||
where("survey_item_id LIKE 't-%'")
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,100 +5,4 @@ class SurveyItemResponse < ActiveRecord::Base
|
|||
belongs_to :academic_year
|
||||
belongs_to :school
|
||||
belongs_to :survey_item
|
||||
|
||||
def self.score_for_subcategory(subcategory:, school:, academic_year:)
|
||||
measures = measures_with_sufficient_data(subcategory: subcategory, school: school, academic_year: academic_year)
|
||||
|
||||
return nil unless measures.size.positive?
|
||||
|
||||
measures.map do |measure|
|
||||
responses_for_measure(measure: measure, school: school, academic_year: academic_year).average(:likert_score)
|
||||
end.average
|
||||
end
|
||||
|
||||
def self.measures_with_sufficient_data(subcategory:, school:, academic_year:)
|
||||
subcategory.measures.select do |measure|
|
||||
sufficient_data?(measure: measure, school: school, academic_year: academic_year)
|
||||
end
|
||||
end
|
||||
|
||||
def self.responses_for_measure(measure:, school:, academic_year:)
|
||||
meets_teacher_threshold = teacher_sufficient_data? measure: measure, school: school, academic_year: academic_year
|
||||
meets_student_threshold = student_sufficient_data? measure: measure, school: school, academic_year: academic_year
|
||||
meets_all_thresholds = meets_teacher_threshold && meets_student_threshold
|
||||
|
||||
if meets_all_thresholds
|
||||
SurveyItemResponse.for_measure(measure, school, academic_year)
|
||||
elsif meets_teacher_threshold
|
||||
SurveyItemResponse.teacher_responses_for_measure(measure, school, academic_year)
|
||||
elsif meets_student_threshold
|
||||
SurveyItemResponse.student_responses_for_measure(measure, school, academic_year)
|
||||
end
|
||||
end
|
||||
|
||||
def self.score_for_measure(measure:, school:, academic_year:)
|
||||
meets_teacher_threshold = teacher_sufficient_data? measure: measure, school: school, academic_year: academic_year
|
||||
meets_student_threshold = student_sufficient_data? measure: measure, school: school, academic_year: academic_year
|
||||
|
||||
survey_item_responses = responses_for_measure(measure: measure, school: school, academic_year: academic_year)
|
||||
|
||||
score_for_measure = survey_item_responses.average(:likert_score) unless survey_item_responses.nil?
|
||||
|
||||
Score.new(score_for_measure, meets_teacher_threshold, meets_student_threshold)
|
||||
end
|
||||
|
||||
def self.sufficient_data?(measure:, school:, academic_year:)
|
||||
meets_teacher_threshold = teacher_sufficient_data? measure: measure, school: school, academic_year: academic_year
|
||||
meets_student_threshold = student_sufficient_data? measure: measure, school: school, academic_year: academic_year
|
||||
meets_teacher_threshold || meets_student_threshold
|
||||
end
|
||||
|
||||
scope :for_measure, lambda { |measure, school, academic_year|
|
||||
joins(:survey_item)
|
||||
.where('survey_items.measure': measure)
|
||||
.where(school: school, academic_year: academic_year)
|
||||
}
|
||||
scope :for_measures, lambda { |measures, school, academic_year|
|
||||
joins(:survey_item)
|
||||
.where('survey_items.measure': measures)
|
||||
.where(school: school, academic_year: academic_year)
|
||||
}
|
||||
|
||||
scope :teacher_responses_for_measure, lambda { |measure, school, academic_year|
|
||||
for_measure(measure, school, academic_year)
|
||||
.where("survey_items.survey_item_id LIKE 't-%'")
|
||||
}
|
||||
scope :teacher_responses_for_measures, lambda { |measures, school, academic_year|
|
||||
for_measures(measures, school, academic_year)
|
||||
.where("survey_items.survey_item_id LIKE 't-%'")
|
||||
}
|
||||
scope :student_responses_for_measure, lambda { |measure, school, academic_year|
|
||||
for_measure(measure, school, academic_year)
|
||||
.where("survey_items.survey_item_id LIKE 's-%'")
|
||||
}
|
||||
|
||||
scope :student_responses_for_measures, lambda { |measures, school, academic_year|
|
||||
for_measures(measures, school, academic_year)
|
||||
.where("survey_items.survey_item_id LIKE 's-%'")
|
||||
}
|
||||
def self.student_sufficient_data?(measure:, school:, academic_year:)
|
||||
if measure.includes_student_survey_items?
|
||||
student_survey_item_responses = SurveyItemResponse.student_responses_for_measure(measure, school, academic_year)
|
||||
average_number_of_survey_item_responses = student_survey_item_responses.count / measure.student_survey_items.count
|
||||
|
||||
meets_student_threshold = average_number_of_survey_item_responses >= STUDENT_RESPONSE_THRESHOLD
|
||||
end
|
||||
!!meets_student_threshold
|
||||
end
|
||||
|
||||
def self.teacher_sufficient_data?(measure:, school:, academic_year:)
|
||||
if measure.includes_teacher_survey_items?
|
||||
teacher_survey_item_responses = SurveyItemResponse.teacher_responses_for_measure(measure, school, academic_year)
|
||||
average_number_of_survey_item_responses = teacher_survey_item_responses.count / measure.teacher_survey_items.count
|
||||
|
||||
meets_teacher_threshold = average_number_of_survey_item_responses >= TEACHER_RESPONSE_THRESHOLD
|
||||
end
|
||||
!!meets_teacher_threshold
|
||||
end
|
||||
private_class_method :measures_with_sufficient_data
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
class TeacherResponseRate < ResponseRate
|
||||
class TeacherResponseRate
|
||||
include ResponseRate
|
||||
|
||||
def rate
|
||||
cap_at_100(super)
|
||||
end
|
||||
|
|
@ -10,12 +12,15 @@ class TeacherResponseRate < ResponseRate
|
|||
end
|
||||
|
||||
def survey_item_count
|
||||
@teacher_survey_item_count ||= SurveyItem.teacher_survey_items_for_measures(@subcategory.measures).count
|
||||
@teacher_survey_item_count ||= @subcategory.measures.map { |measure| measure.teacher_survey_items.count }.sum
|
||||
end
|
||||
|
||||
def response_count
|
||||
@teacher_response_count ||= SurveyItemResponse.teacher_responses_for_measures(@subcategory.measures, @school,
|
||||
@academic_year).count
|
||||
@teacher_response_count ||= @subcategory.measures.map do |measure|
|
||||
measure.teacher_survey_items.map do |survey_item|
|
||||
survey_item.survey_item_responses.where(school: @school, academic_year: @academic_year).count
|
||||
end.sum
|
||||
end.sum
|
||||
end
|
||||
|
||||
def total_possible_responses
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
class GaugePresenter
|
||||
def initialize(scale:, score:)
|
||||
@scale = scale
|
||||
def initialize(zones:, score:)
|
||||
@zones = zones
|
||||
@score = score
|
||||
end
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ class GaugePresenter
|
|||
end
|
||||
|
||||
def key_benchmark_percentage
|
||||
percentage_for @scale.approval_zone.low_benchmark
|
||||
percentage_for @zones.approval_zone.low_benchmark
|
||||
end
|
||||
|
||||
def boundary_percentage_for(zone)
|
||||
|
|
@ -38,31 +38,31 @@ class GaugePresenter
|
|||
private
|
||||
|
||||
def watch_low_boundary
|
||||
percentage_for @scale.watch_zone.low_benchmark
|
||||
percentage_for @zones.watch_zone.low_benchmark
|
||||
end
|
||||
|
||||
def growth_low_boundary
|
||||
percentage_for @scale.growth_zone.low_benchmark
|
||||
percentage_for @zones.growth_zone.low_benchmark
|
||||
end
|
||||
|
||||
def approval_low_boundary
|
||||
percentage_for @scale.approval_zone.low_benchmark
|
||||
percentage_for @zones.approval_zone.low_benchmark
|
||||
end
|
||||
|
||||
def ideal_low_boundary
|
||||
percentage_for @scale.ideal_zone.low_benchmark
|
||||
percentage_for @zones.ideal_zone.low_benchmark
|
||||
end
|
||||
|
||||
def zone
|
||||
@scale.zone_for_score(@score)
|
||||
@zones.zone_for_score(@score)
|
||||
end
|
||||
|
||||
def percentage_for(number)
|
||||
return nil if number.nil?
|
||||
|
||||
scale_minimum = @scale.warning_zone.low_benchmark
|
||||
scale_maximum = @scale.ideal_zone.high_benchmark
|
||||
zones_minimum = @zones.warning_zone.low_benchmark
|
||||
zones_maximum = @zones.ideal_zone.high_benchmark
|
||||
|
||||
(number - scale_minimum) / (scale_maximum - scale_minimum)
|
||||
(number - zones_minimum) / (zones_maximum - zones_minimum)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class MeasurePresenter
|
|||
end
|
||||
|
||||
def gauge_presenter
|
||||
GaugePresenter.new(scale: scale, score: score_for_measure.average)
|
||||
GaugePresenter.new(zones:, score: score_for_measure.average)
|
||||
end
|
||||
|
||||
def data_item_accordion_id
|
||||
|
|
@ -45,11 +45,11 @@ class MeasurePresenter
|
|||
private
|
||||
|
||||
def score_for_measure
|
||||
@score ||= SurveyItemResponse.score_for_measure(measure: @measure, academic_year: @academic_year, school: @school)
|
||||
@score ||= @measure.score(school: @school, academic_year: @academic_year)
|
||||
end
|
||||
|
||||
def scale
|
||||
Scale.new(
|
||||
def zones
|
||||
Zones.new(
|
||||
watch_low_benchmark: @measure.watch_low_benchmark,
|
||||
growth_low_benchmark: @measure.growth_low_benchmark,
|
||||
approval_low_benchmark: @measure.approval_low_benchmark,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
class SubcategoryCardPresenter
|
||||
attr_reader :name
|
||||
|
||||
def initialize(name:, scale:, score:)
|
||||
def initialize(name:, zones:, score:)
|
||||
@name = name
|
||||
@scale = scale
|
||||
@zones = zones
|
||||
@score = score
|
||||
end
|
||||
|
||||
|
|
@ -22,6 +22,6 @@ class SubcategoryCardPresenter
|
|||
private
|
||||
|
||||
def zone
|
||||
@scale.zone_for_score(@score)
|
||||
@zones.zone_for_score(@score)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,16 +22,15 @@ class SubcategoryPresenter
|
|||
end
|
||||
|
||||
def gauge_presenter
|
||||
GaugePresenter.new(scale:, score: average_score)
|
||||
GaugePresenter.new(zones:, score: average_score)
|
||||
end
|
||||
|
||||
def subcategory_card_presenter
|
||||
SubcategoryCardPresenter.new(name: @subcategory.name, scale:, score: average_score)
|
||||
SubcategoryCardPresenter.new(name: @subcategory.name, zones:, score: average_score)
|
||||
end
|
||||
|
||||
def average_score
|
||||
@average_score ||= SurveyItemResponse.score_for_subcategory(subcategory: @subcategory, school: @school,
|
||||
academic_year: @academic_year)
|
||||
@average_score ||= @subcategory.score(school: @school, academic_year: @academic_year)
|
||||
end
|
||||
|
||||
def student_response_rate
|
||||
|
|
@ -48,7 +47,7 @@ class SubcategoryPresenter
|
|||
end
|
||||
|
||||
def measure_presenters
|
||||
@subcategory.measures.includes([:admin_data_items]).sort_by(&:measure_id).map do |measure|
|
||||
@subcategory.measures.sort_by(&:measure_id).map do |measure|
|
||||
MeasurePresenter.new(measure:, academic_year: @academic_year, school: @school)
|
||||
end
|
||||
end
|
||||
|
|
@ -56,19 +55,17 @@ class SubcategoryPresenter
|
|||
private
|
||||
|
||||
def admin_data_item_count
|
||||
if @school.is_hs
|
||||
AdminDataItem.for_measures(@subcategory.measures).count
|
||||
else
|
||||
AdminDataItem.non_hs_items_for_measures(@subcategory.measures).count
|
||||
end
|
||||
return AdminDataItem.for_measures(@subcategory.measures).count if @school.is_hs
|
||||
|
||||
AdminDataItem.non_hs_items_for_measures(@subcategory.measures).count
|
||||
end
|
||||
|
||||
def format_a_non_applicable_rate(rate)
|
||||
rate == [0, 0] ? %w[N A] : rate
|
||||
end
|
||||
|
||||
def scale
|
||||
Scale.new(
|
||||
def zones
|
||||
Zones.new(
|
||||
watch_low_benchmark: measures.map(&:watch_low_benchmark).average,
|
||||
growth_low_benchmark: measures.map(&:growth_low_benchmark).average,
|
||||
approval_low_benchmark: measures.map(&:approval_low_benchmark).average,
|
||||
|
|
|
|||
|
|
@ -96,12 +96,12 @@ class VarianceChartRowPresenter
|
|||
end
|
||||
|
||||
def zone
|
||||
scale = Scale.new(
|
||||
zones = Zones.new(
|
||||
watch_low_benchmark: @measure.watch_low_benchmark,
|
||||
growth_low_benchmark: @measure.growth_low_benchmark,
|
||||
approval_low_benchmark: @measure.approval_low_benchmark,
|
||||
ideal_low_benchmark: @measure.ideal_low_benchmark
|
||||
)
|
||||
scale.zone_for_score(@score)
|
||||
zones.zone_for_score(@score)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
class Scale
|
||||
class Zones
|
||||
def initialize(watch_low_benchmark:, growth_low_benchmark:, approval_low_benchmark:, ideal_low_benchmark:)
|
||||
@watch_low_benchmark = watch_low_benchmark
|
||||
@growth_low_benchmark = growth_low_benchmark
|
||||
|
|
@ -34,9 +34,10 @@ class Scale
|
|||
end
|
||||
|
||||
def zone_for_score(score)
|
||||
return insufficient_data if score.nil?
|
||||
return insufficient_data if score.is_a?(Float) && score.nan?
|
||||
|
||||
case score
|
||||
when nil
|
||||
insufficient_data
|
||||
when ideal_zone.low_benchmark..ideal_zone.high_benchmark
|
||||
ideal_zone
|
||||
when approval_zone.low_benchmark..approval_zone.high_benchmark
|
||||
Loading…
Add table
Add a link
Reference in a new issue