mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-07 21:48:16 -08:00
Modify score calculations. Ignore any survey item scores of 0.
Never include zero when performing calculations for scores.
This commit is contained in:
parent
0e85370b90
commit
c475744939
5 changed files with 99 additions and 32 deletions
|
|
@ -50,20 +50,17 @@ class Measure < ActiveRecord::Base
|
||||||
meets_student_threshold = sufficient_student_data?(school:, academic_year:)
|
meets_student_threshold = sufficient_student_data?(school:, academic_year:)
|
||||||
meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:)
|
meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:)
|
||||||
meets_admin_data_threshold = all_admin_data_collected?(school:, academic_year:)
|
meets_admin_data_threshold = all_admin_data_collected?(school:, academic_year:)
|
||||||
lacks_sufficient_data = !meets_student_threshold && !meets_teacher_threshold && !includes_admin_data_items?
|
lacks_sufficient_survey_data = !meets_student_threshold && !meets_teacher_threshold
|
||||||
|
incalculable_score = lacks_sufficient_survey_data && !includes_admin_data_items?
|
||||||
|
|
||||||
next Score.new(nil, false, false, false) if lacks_sufficient_data
|
next Score.new(nil, false, false, false) if incalculable_score
|
||||||
|
|
||||||
scores = []
|
scores = []
|
||||||
scores << teacher_scales.map { |scale| scale.score(school:, academic_year:) }.average if meets_teacher_threshold
|
scores << collect_survey_scale_average(teacher_scales, school, academic_year) if meets_teacher_threshold
|
||||||
scores << student_scales.map { |scale| scale.score(school:, academic_year:) }.average if meets_student_threshold
|
scores << collect_survey_scale_average(student_scales, school, academic_year) if meets_student_threshold
|
||||||
if includes_admin_data_items?
|
scores << collect_admin_scale_average(admin_data_items, school, academic_year) if includes_admin_data_items?
|
||||||
scores << admin_data_items.map do |admin_data_item|
|
|
||||||
admin_value = admin_data_item.admin_data_values.where(school:, academic_year:).first
|
average = scores.flatten.compact.remove_zeros.average
|
||||||
admin_value.likert_score if admin_value.present?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
average = scores.flatten.compact.average
|
|
||||||
|
|
||||||
next Score.new(nil, false, false, false) if average.nan?
|
next Score.new(nil, false, false, false) if average.nan?
|
||||||
|
|
||||||
|
|
@ -122,6 +119,17 @@ class Measure < ActiveRecord::Base
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def collect_survey_scale_average(scales, school, academic_year)
|
||||||
|
scales.map { |scale| scale.score(school:, academic_year:) }.average
|
||||||
|
end
|
||||||
|
|
||||||
|
def collect_admin_scale_average(scales, school, academic_year)
|
||||||
|
scales.map do |admin_data_item|
|
||||||
|
admin_value = admin_data_item.admin_data_values.where(school:, academic_year:).first
|
||||||
|
admin_value.likert_score if admin_value.present?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def benchmark(name)
|
def benchmark(name)
|
||||||
averages = []
|
averages = []
|
||||||
averages << student_survey_items.first.send(name) if includes_student_survey_items?
|
averages << student_survey_items.first.send(name) if includes_student_survey_items?
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,10 @@ class Scale < ApplicationRecord
|
||||||
@score ||= Hash.new do |memo|
|
@score ||= Hash.new do |memo|
|
||||||
memo[[school, academic_year]] = begin
|
memo[[school, academic_year]] = begin
|
||||||
items = []
|
items = []
|
||||||
items << student_survey_items(school:, academic_year:)
|
items << collect_survey_item_average(student_survey_items(school:, academic_year:), school, academic_year)
|
||||||
items << teacher_survey_items
|
items << collect_survey_item_average(teacher_survey_items, school, academic_year)
|
||||||
|
|
||||||
items.flatten.map do |survey_item|
|
items.remove_zeros.average
|
||||||
survey_item.score(school:, academic_year:)
|
|
||||||
end.average
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@score[[school, academic_year]]
|
@score[[school, academic_year]]
|
||||||
|
|
@ -28,6 +26,12 @@ class Scale < ApplicationRecord
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def collect_survey_item_average(survey_items, school, academic_year)
|
||||||
|
survey_items.map do |survey_item|
|
||||||
|
survey_item.score(school:, academic_year:)
|
||||||
|
end.remove_zeros.average
|
||||||
|
end
|
||||||
|
|
||||||
def teacher_survey_items
|
def teacher_survey_items
|
||||||
survey_items.teacher_survey_items
|
survey_items.teacher_survey_items
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@ module ArrayMonkeyPatches
|
||||||
def average
|
def average
|
||||||
sum.to_f / size
|
sum.to_f / size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_zeros
|
||||||
|
reject { |item| item == 0 || item.to_f.nan? }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Array.include ArrayMonkeyPatches
|
Array.include ArrayMonkeyPatches
|
||||||
|
|
|
||||||
19
doc/architectural_decision_records/9.md
Normal file
19
doc/architectural_decision_records/9.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Decision record 9
|
||||||
|
|
||||||
|
# Modify score calculations so that a survey item score of 0 is never included in the average
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Completed
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Some scores were artificially low because survey items that lacked survey item responses returned a score of 0. 0 did not represent the average likert_scores of survey item responses, only the lack of responses. 0 was incorrectly being averaged with other survey items and artificially dragging down the score.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Survey item scores of 0 should be ignored and filtered out when performing score calculations.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
Some average scores have increased.
|
||||||
|
|
@ -12,32 +12,64 @@ RSpec.describe Scale, type: :model do
|
||||||
let(:teacher_survey_item_1) { create(:teacher_survey_item, scale:) }
|
let(:teacher_survey_item_1) { create(:teacher_survey_item, scale:) }
|
||||||
let(:teacher_survey_item_2) { create(:teacher_survey_item, scale:) }
|
let(:teacher_survey_item_2) { create(:teacher_survey_item, scale:) }
|
||||||
let(:teacher_survey_item_3) { create(:teacher_survey_item, scale:) }
|
let(:teacher_survey_item_3) { create(:teacher_survey_item, scale:) }
|
||||||
|
let(:student_survey_item_1) { create(:student_survey_item, scale:) }
|
||||||
|
|
||||||
before :each do
|
context 'when only teacher survey items exist' do
|
||||||
|
before :each do
|
||||||
|
create(:survey_item_response,
|
||||||
|
survey_item: teacher_survey_item_1, academic_year:, school:, likert_score: 3)
|
||||||
|
create(:survey_item_response,
|
||||||
|
survey_item: teacher_survey_item_2, academic_year:, school:, likert_score: 4)
|
||||||
|
create(:survey_item_response,
|
||||||
|
survey_item: teacher_survey_item_3, academic_year:, school:, likert_score: 5)
|
||||||
|
end
|
||||||
|
it 'returns the average of the likert scores of the survey items' do
|
||||||
|
expect(scale.score(school:, academic_year:)).to eq 4
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when other scales exist' do
|
||||||
|
before :each do
|
||||||
|
create(:survey_item_response,
|
||||||
|
academic_year:, school:, likert_score: 1)
|
||||||
|
create(:survey_item_response,
|
||||||
|
academic_year:, school:, likert_score: 1)
|
||||||
|
create(:survey_item_response,
|
||||||
|
academic_year:, school:, likert_score: 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not affect the score for the original scale' do
|
||||||
|
expect(scale.score(school:, academic_year:)).to eq 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when both teacher and student survey items exist' do
|
||||||
|
before :each do
|
||||||
create(:survey_item_response,
|
create(:survey_item_response,
|
||||||
survey_item: teacher_survey_item_1, academic_year:, school:, likert_score: 3)
|
survey_item: teacher_survey_item_1, academic_year:, school:, likert_score: 3)
|
||||||
create(:survey_item_response,
|
create(:survey_item_response,
|
||||||
survey_item: teacher_survey_item_2, academic_year:, school:, likert_score: 4)
|
survey_item: teacher_survey_item_2, academic_year:, school:, likert_score: 4)
|
||||||
create(:survey_item_response,
|
create(:survey_item_response,
|
||||||
survey_item: teacher_survey_item_3, academic_year:, school:, likert_score: 5)
|
survey_item: teacher_survey_item_3, academic_year:, school:, likert_score: 5)
|
||||||
end
|
end
|
||||||
|
context 'but no survey item responses are linked to student survey items' do
|
||||||
|
before :each do
|
||||||
|
student_survey_item_1
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns the average of the likert scores of the survey items' do
|
it 'returns a score that only averages teacher survey items' do
|
||||||
expect(scale.score(school:, academic_year:)).to eq 4
|
expect(scale.score(school:, academic_year:)).to eq 4
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when other scales exist' do
|
|
||||||
before :each do
|
|
||||||
create(:survey_item_response,
|
|
||||||
academic_year:, school:, likert_score: 1)
|
|
||||||
create(:survey_item_response,
|
|
||||||
academic_year:, school:, likert_score: 1)
|
|
||||||
create(:survey_item_response,
|
|
||||||
academic_year:, school:, likert_score: 1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not affect the score for the original scale' do
|
context 'and some survey item responses exist for a student survey item' do
|
||||||
expect(scale.score(school:, academic_year:)).to eq 4
|
before :each do
|
||||||
|
create(:survey_item_response,
|
||||||
|
survey_item: student_survey_item_1, academic_year:, school:, likert_score: 2)
|
||||||
|
end
|
||||||
|
it 'returns a score that gives equal weight to student and teacher survey items' do
|
||||||
|
expect(scale.score(school:, academic_year:)).to eq 3
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue