mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-07 21:48:16 -08:00
Finishes #183092367. Adds ui and graphs to show grade level disaggregations
This commit is contained in:
parent
6ed405d16d
commit
89a7f27b88
47 changed files with 20889 additions and 21051 deletions
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
class AnalyzeController < SqmApplicationController
|
class AnalyzeController < SqmApplicationController
|
||||||
before_action :assign_categories, :assign_subcategories, :assign_measures, :assign_academic_years,
|
before_action :assign_categories, :assign_subcategories, :assign_measures, :assign_academic_years,
|
||||||
:response_rate_timestamp, :races, :selected_races, :graph, :graphs, :background, :race_score_timestamp, only: [:index]
|
:response_rate_timestamp, :races, :selected_races, :graph, :graphs, :background, :race_score_timestamp,
|
||||||
|
:sources, :group, :groups, :selected_grades, :grades, :slice, only: [:index]
|
||||||
def index; end
|
def index; end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
@ -67,14 +68,15 @@ class AnalyzeController < SqmApplicationController
|
||||||
|
|
||||||
def graph
|
def graph
|
||||||
graphs.each do |graph|
|
graphs.each do |graph|
|
||||||
@graph = graph if graph.value == params[:graph]
|
@graph = graph if graph.slug == params[:graph]
|
||||||
end
|
end
|
||||||
|
|
||||||
@graph ||= graphs.first
|
@graph ||= graphs.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def graphs
|
def graphs
|
||||||
@graphs ||= [Analyze::Graph::StudentsAndTeachers.new, Analyze::Graph::StudentsByGroup.new(races: selected_races)]
|
@graphs ||= [Analyze::Graph::StudentsAndTeachers.new, Analyze::Graph::StudentsByRace.new(races: selected_races),
|
||||||
|
Analyze::Graph::StudentsByGrade.new(grades: selected_grades)]
|
||||||
end
|
end
|
||||||
|
|
||||||
def background
|
def background
|
||||||
|
|
@ -88,4 +90,61 @@ class AnalyzeController < SqmApplicationController
|
||||||
score.updated_at
|
score.updated_at
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sources
|
||||||
|
@sources = [Analyze::Source::SurveyData.new(slices:)]
|
||||||
|
end
|
||||||
|
|
||||||
|
def slices
|
||||||
|
students_and_teachers = Analyze::Slice::StudentsAndTeachers.new
|
||||||
|
students_by_group = Analyze::Slice::StudentsByGroup.new(races:, grades:)
|
||||||
|
[students_and_teachers, students_by_group]
|
||||||
|
end
|
||||||
|
|
||||||
|
def group
|
||||||
|
groups.each do |group|
|
||||||
|
@group = group if group.slug == params[:group]
|
||||||
|
end
|
||||||
|
|
||||||
|
@group ||= groups.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def groups
|
||||||
|
@groups = [Analyze::Group::Race.new, Analyze::Group::Grade.new]
|
||||||
|
end
|
||||||
|
|
||||||
|
def selected_grades
|
||||||
|
@selected_grades ||= begin
|
||||||
|
grade_params = params[:grades]
|
||||||
|
return @selected_grades = grades unless grade_params
|
||||||
|
|
||||||
|
grade_list = grade_params.split(',') if grade_params
|
||||||
|
if grade_list
|
||||||
|
grade_list = grade_list.map do |grade|
|
||||||
|
grade.to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
grade_list
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def grades
|
||||||
|
@grades ||= SurveyItemResponse.where(school: @school, academic_year: @academic_year)
|
||||||
|
.where.not(grade: nil)
|
||||||
|
.group(:grade)
|
||||||
|
.select(:response_id)
|
||||||
|
.distinct(:response_id)
|
||||||
|
.count.reject do |_key, value|
|
||||||
|
value < 10
|
||||||
|
end.keys
|
||||||
|
end
|
||||||
|
|
||||||
|
def slice
|
||||||
|
slice_param = params[:slice]
|
||||||
|
slices.each do |slice|
|
||||||
|
@slice = slice if slice.slug == slice_param
|
||||||
|
end
|
||||||
|
|
||||||
|
@slice ||= slices.first
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,16 @@ export default class extends Controller {
|
||||||
base_url +
|
base_url +
|
||||||
"&academic_years=" +
|
"&academic_years=" +
|
||||||
this.selected_years().join(",") +
|
this.selected_years().join(",") +
|
||||||
|
"&group=" +
|
||||||
|
this.selected_group() +
|
||||||
|
"&slice=" +
|
||||||
|
this.selected_slice() +
|
||||||
"&graph=" +
|
"&graph=" +
|
||||||
this.selected_graph() +
|
this.selected_graph() +
|
||||||
"&races=" +
|
"&races=" +
|
||||||
this.selected_races().join(",");
|
this.selected_races().join(",") +
|
||||||
|
"&grades=" +
|
||||||
|
this.selected_grades().join(",");
|
||||||
|
|
||||||
this.go_to(url);
|
this.go_to(url);
|
||||||
}
|
}
|
||||||
|
|
@ -36,9 +42,22 @@ export default class extends Controller {
|
||||||
return years;
|
return years;
|
||||||
}
|
}
|
||||||
|
|
||||||
selected_graph() {
|
selected_group() {
|
||||||
let graphs = [...document.getElementsByName("graph")];
|
let groups = [...document.getElementsByName("group-option")];
|
||||||
let selected_graph = graphs
|
let selected_group = groups
|
||||||
|
.filter((item) => {
|
||||||
|
return item.selected;
|
||||||
|
})
|
||||||
|
.map((item) => {
|
||||||
|
return item.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
return selected_group[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
selected_slice() {
|
||||||
|
let slices = [...document.getElementsByName("slice")];
|
||||||
|
let selected_slice = slices
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
return item.checked;
|
return item.checked;
|
||||||
})
|
})
|
||||||
|
|
@ -46,7 +65,27 @@ export default class extends Controller {
|
||||||
return item.id;
|
return item.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return selected_graph[0];
|
return selected_slice[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
selected_graph() {
|
||||||
|
let graphs = [...document.getElementsByName("slice")];
|
||||||
|
let selected_graph = graphs
|
||||||
|
.filter((item) => {
|
||||||
|
return item.checked;
|
||||||
|
})
|
||||||
|
.map((item) => {
|
||||||
|
return item.id;
|
||||||
|
})[0];
|
||||||
|
if (selected_graph === 'students-and-teachers') {
|
||||||
|
return selected_graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selected_group() === 'race') {
|
||||||
|
return 'students-by-race'
|
||||||
|
} else {
|
||||||
|
return 'students-by-grade'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selected_races() {
|
selected_races() {
|
||||||
|
|
@ -61,4 +100,17 @@ export default class extends Controller {
|
||||||
|
|
||||||
return races;
|
return races;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selected_grades() {
|
||||||
|
let grade_checkboxes = [...document.getElementsByName("grade-checkbox")]
|
||||||
|
let grades = grade_checkboxes
|
||||||
|
.filter((item) => {
|
||||||
|
return item.checked;
|
||||||
|
})
|
||||||
|
.map((item) => {
|
||||||
|
return item.id.replace('grade-', '');
|
||||||
|
});
|
||||||
|
|
||||||
|
return grades;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ 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 = any_admin_data_collected?(school:, academic_year:)
|
meets_admin_data_threshold = any_admin_data_collected?(school:, academic_year:)
|
||||||
Score.new(average, meets_teacher_threshold, meets_student_threshold, meets_admin_data_threshold)
|
Score.new(average:, meets_teacher_threshold:, meets_student_threshold:, meets_admin_data_threshold:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect_survey_item_average(survey_items:, school:, academic_year:)
|
def collect_survey_item_average(survey_items:, school:, academic_year:)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,20 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Score < Struct.new(:average, :meets_teacher_threshold?, :meets_student_threshold?, :meets_admin_data_threshold?)
|
class Score < ApplicationRecord
|
||||||
NIL_SCORE = Score.new(nil, false, false, false)
|
belongs_to :measure
|
||||||
|
belongs_to :school
|
||||||
|
belongs_to :academic_year
|
||||||
|
belongs_to :race
|
||||||
|
|
||||||
|
NIL_SCORE = Score.new(average: nil, meets_teacher_threshold: false, meets_student_threshold: false, meets_admin_data_threshold: false)
|
||||||
|
|
||||||
|
enum group: {
|
||||||
|
all_students: 0,
|
||||||
|
race: 1,
|
||||||
|
grade: 2,
|
||||||
|
gender: 3
|
||||||
|
}
|
||||||
|
|
||||||
def in_zone?(zone:)
|
def in_zone?(zone:)
|
||||||
return false if average.nil? || average.is_a?(Float) && average.nan?
|
return false if average.nil? || average.is_a?(Float) && average.nan?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,10 @@ class SurveyItemResponse < ActiveRecord::Base
|
||||||
boston = District.find_by_name('Boston')
|
boston = District.find_by_name('Boston')
|
||||||
where.not(school: boston.schools) if boston.present?
|
where.not(school: boston.schools) if boston.present?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope :averages_for_grade, ->(survey_items, school, academic_year, grade) {
|
||||||
|
SurveyItemResponse.where(survey_item: survey_items, school:,
|
||||||
|
academic_year: , grade:).group(:survey_item).average(:likert_score)
|
||||||
|
}
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
33
app/presenters/analyze/graph/column/grade/eight.rb
Normal file
33
app/presenters/analyze/graph/column/grade/eight.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Eight < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
|
|
||||||
33
app/presenters/analyze/graph/column/grade/eleven.rb
Normal file
33
app/presenters/analyze/graph/column/grade/eleven.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Eleven < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
|
|
||||||
32
app/presenters/analyze/graph/column/grade/five.rb
Normal file
32
app/presenters/analyze/graph/column/grade/five.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Five < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
32
app/presenters/analyze/graph/column/grade/four.rb
Normal file
32
app/presenters/analyze/graph/column/grade/four.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Four < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
34
app/presenters/analyze/graph/column/grade/nine.rb
Normal file
34
app/presenters/analyze/graph/column/grade/nine.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Nine < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
|
|
||||||
|
|
||||||
32
app/presenters/analyze/graph/column/grade/one.rb
Normal file
32
app/presenters/analyze/graph/column/grade/one.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class One < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
27
app/presenters/analyze/graph/column/grade/score_for_grade.rb
Normal file
27
app/presenters/analyze/graph/column/grade/score_for_grade.rb
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
module ScoreForGrade
|
||||||
|
def score(year_index)
|
||||||
|
averages = SurveyItemResponse.averages_for_grade(measure.student_survey_items, school, academic_years[year_index], grade)
|
||||||
|
average = bubble_up_averages(averages:)
|
||||||
|
|
||||||
|
Score.new(average:,
|
||||||
|
meets_teacher_threshold: false,
|
||||||
|
meets_student_threshold: true,
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
32
app/presenters/analyze/graph/column/grade/seven.rb
Normal file
32
app/presenters/analyze/graph/column/grade/seven.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Seven < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
32
app/presenters/analyze/graph/column/grade/six.rb
Normal file
32
app/presenters/analyze/graph/column/grade/six.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Six < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
34
app/presenters/analyze/graph/column/grade/ten.rb
Normal file
34
app/presenters/analyze/graph/column/grade/ten.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Ten < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
|
|
||||||
|
|
||||||
32
app/presenters/analyze/graph/column/grade/three.rb
Normal file
32
app/presenters/analyze/graph/column/grade/three.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Three < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
34
app/presenters/analyze/graph/column/grade/twelve.rb
Normal file
34
app/presenters/analyze/graph/column/grade/twelve.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Twelve < GroupedBarColumnPresenter
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
|
|
||||||
|
|
||||||
34
app/presenters/analyze/graph/column/grade/two.rb
Normal file
34
app/presenters/analyze/graph/column/grade/two.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
module Column
|
||||||
|
module Grade
|
||||||
|
class Two < GroupedBarColumnPresenter
|
||||||
|
attr_reader :sufficient_responses
|
||||||
|
|
||||||
|
include Analyze::Graph::Column::Grade::ScoreForGrade
|
||||||
|
def label
|
||||||
|
'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
|
||||||
|
|
@ -8,7 +8,10 @@ module Analyze
|
||||||
average ||= 0
|
average ||= 0
|
||||||
meets_student_threshold = s.meets_student_threshold? unless s.nil?
|
meets_student_threshold = s.meets_student_threshold? unless s.nil?
|
||||||
meets_student_threshold ||= false
|
meets_student_threshold ||= false
|
||||||
Score.new(average, false, meets_student_threshold, false)
|
Score.new(average:,
|
||||||
|
meets_teacher_threshold: false,
|
||||||
|
meets_student_threshold:,
|
||||||
|
meets_admin_data_threshold: false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ module Analyze
|
||||||
'Students & Teachers'
|
'Students & Teachers'
|
||||||
end
|
end
|
||||||
|
|
||||||
def value
|
def slug
|
||||||
'students-and-teachers'
|
'students-and-teachers'
|
||||||
end
|
end
|
||||||
|
|
||||||
50
app/presenters/analyze/graph/students_by_grade.rb
Normal file
50
app/presenters/analyze/graph/students_by_grade.rb
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
module Analyze
|
||||||
|
module Graph
|
||||||
|
class StudentsByGrade
|
||||||
|
include Analyze::Graph::Column::Grade
|
||||||
|
attr_reader :grades
|
||||||
|
|
||||||
|
def initialize(grades:)
|
||||||
|
@grades = grades
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
'Students by Grade'
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug
|
||||||
|
'students-by-grade'
|
||||||
|
end
|
||||||
|
|
||||||
|
def columns
|
||||||
|
[].tap do |array|
|
||||||
|
grades.each do |grade|
|
||||||
|
array << column_for_grade_code(code: grade)
|
||||||
|
end
|
||||||
|
array << Analyze::Graph::Column::AllStudent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def column_for_grade_code(code:)
|
||||||
|
CFR[code]
|
||||||
|
end
|
||||||
|
|
||||||
|
CFR = {
|
||||||
|
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
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
module Analyze
|
module Analyze
|
||||||
module Graph
|
module Graph
|
||||||
class StudentsByGroup
|
class StudentsByRace
|
||||||
attr_reader :races
|
attr_reader :races
|
||||||
|
|
||||||
def initialize(races:)
|
def initialize(races:)
|
||||||
|
|
@ -8,11 +8,11 @@ module Analyze
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
'Students by Group'
|
'Students by Race'
|
||||||
end
|
end
|
||||||
|
|
||||||
def value
|
def slug
|
||||||
'students-by-group'
|
'students-by-race'
|
||||||
end
|
end
|
||||||
|
|
||||||
def columns
|
def columns
|
||||||
|
|
@ -39,7 +39,7 @@ module Analyze
|
||||||
'8' => Analyze::Graph::Column::MiddleEastern,
|
'8' => Analyze::Graph::Column::MiddleEastern,
|
||||||
'99' => Analyze::Graph::Column::Unknown,
|
'99' => Analyze::Graph::Column::Unknown,
|
||||||
'100' => Analyze::Graph::Column::Multiracial
|
'100' => Analyze::Graph::Column::Multiracial
|
||||||
}
|
}.freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
13
app/presenters/analyze/group/grade.rb
Normal file
13
app/presenters/analyze/group/grade.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
module Analyze
|
||||||
|
module Group
|
||||||
|
class Grade
|
||||||
|
def name
|
||||||
|
'Grade'
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug
|
||||||
|
'grade'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
13
app/presenters/analyze/group/race.rb
Normal file
13
app/presenters/analyze/group/race.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
module Analyze
|
||||||
|
module Group
|
||||||
|
class Race
|
||||||
|
def name
|
||||||
|
'Race'
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug
|
||||||
|
'race'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
17
app/presenters/analyze/slice/students_and_teachers.rb
Normal file
17
app/presenters/analyze/slice/students_and_teachers.rb
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
module Analyze
|
||||||
|
module Slice
|
||||||
|
class StudentsAndTeachers
|
||||||
|
def to_s
|
||||||
|
'Students & Teachers'
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug
|
||||||
|
'students-and-teachers'
|
||||||
|
end
|
||||||
|
|
||||||
|
def graphs
|
||||||
|
[Analyze::Graph::StudentsAndTeachers.new]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
24
app/presenters/analyze/slice/students_by_group.rb
Normal file
24
app/presenters/analyze/slice/students_by_group.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
module Analyze
|
||||||
|
module Slice
|
||||||
|
class StudentsByGroup
|
||||||
|
attr_reader :races, :grades
|
||||||
|
|
||||||
|
def initialize(races:, grades:)
|
||||||
|
@races = races
|
||||||
|
@grades = grades
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
'Students by Group'
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug
|
||||||
|
'students-by-group'
|
||||||
|
end
|
||||||
|
|
||||||
|
def graphs
|
||||||
|
[Analyze::Graph::StudentsByRace.new(races:), Analyze::Graph::StudentsByGrade.new(grades:)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
20
app/presenters/analyze/source/survey_data.rb
Normal file
20
app/presenters/analyze/source/survey_data.rb
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
module Analyze
|
||||||
|
module Source
|
||||||
|
class SurveyData
|
||||||
|
attr_reader :slices
|
||||||
|
|
||||||
|
include Analyze::Slice
|
||||||
|
|
||||||
|
def initialize(slices:)
|
||||||
|
@slices = slices
|
||||||
|
end
|
||||||
|
# def to_s
|
||||||
|
# 'Survey Data Only'
|
||||||
|
# end
|
||||||
|
|
||||||
|
# def value
|
||||||
|
# 'survey-data-only'
|
||||||
|
# end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -42,6 +42,6 @@ class Zones
|
||||||
end
|
end
|
||||||
|
|
||||||
def zone_for_score(score)
|
def zone_for_score(score)
|
||||||
all_zones.find { |zone| Score.new(score).in_zone?(zone:) } || insufficient_data
|
all_zones.find { |zone| Score.new(average: score).in_zone?(zone:) } || insufficient_data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,13 @@ class RaceScoreLoader
|
||||||
|
|
||||||
def self.race_score(measure:, school:, academic_year:, race:)
|
def self.race_score(measure:, school:, academic_year:, race:)
|
||||||
rate = response_rate(school:, academic_year:, measure:)
|
rate = response_rate(school:, academic_year:, measure:)
|
||||||
return Score.new(0, false, false, false) unless rate.meets_student_threshold
|
return Score.new(average: 0, meets_teacher_threshold: false, meets_student_threshold: false, meets_admin_data_threshold: false) unless rate.meets_student_threshold
|
||||||
|
|
||||||
survey_items = measure.student_survey_items
|
survey_items = measure.student_survey_items
|
||||||
|
|
||||||
# students = StudentRace.where(race:).pluck(:student_id).uniq
|
|
||||||
averages = grouped_responses(school:, academic_year:, survey_items:, race:)
|
averages = grouped_responses(school:, academic_year:, survey_items:, race:)
|
||||||
meets_student_threshold = sufficient_responses(school:, academic_year:, race:)
|
meets_student_threshold = sufficient_responses(school:, academic_year:, race:)
|
||||||
scorify(responses: averages, meets_student_threshold:, measure:)
|
scorify(responses: averages, meets_student_threshold:, measure:)
|
||||||
# binding.break
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.grouped_responses(school:, academic_year:, survey_items:, race:)
|
def self.grouped_responses(school:, academic_year:, survey_items:, race:)
|
||||||
|
|
@ -83,7 +81,7 @@ class RaceScoreLoader
|
||||||
|
|
||||||
average = 0 unless meets_student_threshold
|
average = 0 unless meets_student_threshold
|
||||||
|
|
||||||
Score.new(average, false, meets_student_threshold, false)
|
Score.new(average:, meets_teacher_threshold: false, meets_student_threshold:, meets_admin_data_threshold: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.sufficient_responses(school:, academic_year:, race:)
|
def self.sufficient_responses(school:, academic_year:, race:)
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,10 @@ class SurveyResponsesDataLoader
|
||||||
def self.load_data(filepath:)
|
def self.load_data(filepath:)
|
||||||
File.open(filepath) do |file|
|
File.open(filepath) do |file|
|
||||||
headers = file.first
|
headers = file.first
|
||||||
survey_items = SurveyItem.where(survey_item_id: get_survey_item_ids_from_headers(headers:))
|
|
||||||
|
|
||||||
file.lazy.each_slice(1000) do |lines|
|
file.lazy.each_slice(1000) do |lines|
|
||||||
survey_item_responses = CSV.parse(lines.join, headers:).map do |row|
|
survey_item_responses = CSV.parse(lines.join, headers:).map do |row|
|
||||||
process_row row: row, survey_items: survey_items
|
process_row row: Values.new(row:, headers:)
|
||||||
end
|
end
|
||||||
|
|
||||||
SurveyItemResponse.import survey_item_responses.compact.flatten, batch_size: 1000
|
SurveyItemResponse.import survey_item_responses.compact.flatten, batch_size: 1000
|
||||||
|
|
@ -20,89 +19,102 @@ class SurveyResponsesDataLoader
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def self.process_row(row:, survey_items:)
|
def self.process_row(row:)
|
||||||
id = dese_id(row)
|
return unless row.dese_id?
|
||||||
return unless dese_id?(id)
|
return unless row.school.present?
|
||||||
|
|
||||||
school = School.find_by_dese_id(id)
|
process_survey_items(row:)
|
||||||
return unless school.present?
|
|
||||||
|
|
||||||
process_survey_items(row:, survey_items:, school:)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.process_survey_items(row:, survey_items:, school:)
|
def self.process_survey_items(row:)
|
||||||
id = response_id(row)
|
row.survey_items.map do |survey_item|
|
||||||
survey_items.map do |survey_item|
|
likert_score = row.likert_score(survey_item_id: survey_item.survey_item_id) || next
|
||||||
likert_score = row[survey_item.survey_item_id] || next
|
|
||||||
|
|
||||||
unless likert_score.valid_likert_score?
|
unless likert_score.valid_likert_score?
|
||||||
puts "Response ID: #{id}, Likert score: #{likert_score} rejected" unless likert_score == 'NA'
|
puts "Response ID: #{row.response_id}, Likert score: #{likert_score} rejected" unless likert_score == 'NA'
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
response = survey_item_response(response_id: id, survey_item:)
|
response = row.survey_item_response(survey_item:)
|
||||||
create_or_update_response(survey_item_response: response, likert_score:, school:, row:, survey_item:)
|
create_or_update_response(survey_item_response: response, likert_score:, row:, survey_item:)
|
||||||
end.compact
|
end.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create_or_update_response(survey_item_response:, likert_score:, school:, row:, survey_item:)
|
def self.create_or_update_response(survey_item_response:, likert_score:, row:, survey_item:)
|
||||||
if survey_item_response.present?
|
if survey_item_response.present?
|
||||||
survey_item_response.update!(likert_score:) if survey_item_response.likert_score != likert_score
|
survey_item_response.update!(likert_score:)
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
SurveyItemResponse.new(response_id: response_id(row), academic_year: academic_year(row), school:, survey_item:,
|
SurveyItemResponse.new(response_id: row.response_id, academic_year: row.academic_year, school: row.school, survey_item:,
|
||||||
likert_score:)
|
likert_score:, grade: row.grade)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get_survey_item_ids_from_headers(headers:)
|
private_class_method :process_row
|
||||||
|
private_class_method :process_survey_items
|
||||||
|
private_class_method :create_or_update_response
|
||||||
|
end
|
||||||
|
|
||||||
|
class Values
|
||||||
|
attr_reader :row, :headers
|
||||||
|
|
||||||
|
def initialize(row:, headers:)
|
||||||
|
@row = row
|
||||||
|
@headers = headers
|
||||||
|
end
|
||||||
|
|
||||||
|
def dese_id?
|
||||||
|
dese_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_date
|
||||||
|
@response_date ||= Date.parse(row['Recorded Date'] || row['RecordedDate'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def academic_year
|
||||||
|
@academic_year ||= AcademicYear.find_by_date response_date
|
||||||
|
end
|
||||||
|
|
||||||
|
def survey_item_response(survey_item:)
|
||||||
|
SurveyItemResponse.find_by(response_id:, survey_item:)
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_id
|
||||||
|
@response_id ||= row['Response ID'] || row['ResponseId'] || row['ResponseID']
|
||||||
|
end
|
||||||
|
|
||||||
|
def dese_id
|
||||||
|
@dese_id ||= (row['DESE ID' || 'Dese ID'] || row['DeseId'] || row['DeseID']).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def likert_score(survey_item_id:)
|
||||||
|
row[survey_item_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def school
|
||||||
|
@school ||= School.find_by_dese_id(dese_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def survey_items
|
||||||
|
@survey_items ||= SurveyItem.where(survey_item_id: get_survey_item_ids_from_headers(headers:))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_survey_item_ids_from_headers(headers:)
|
||||||
CSV.parse(headers, headers: true).headers
|
CSV.parse(headers, headers: true).headers
|
||||||
.filter(&:present?)
|
.filter(&:present?)
|
||||||
.filter { |header| header.start_with? 't-' or header.start_with? 's-' }
|
.filter { |header| header.start_with? 't-' or header.start_with? 's-' }
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.dese_id?(dese_id)
|
def grade
|
||||||
dese_id.present?
|
@grade ||= begin
|
||||||
|
raw_grade = (row['grade'] || row['Grade'] || row['What grade are you in?']).to_i
|
||||||
|
raw_grade == 0 ? nil : raw_grade
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.response_date(row)
|
|
||||||
Date.parse(row['Recorded Date'] || row['RecordedDate'])
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.academic_year(row)
|
|
||||||
AcademicYear.find_by_date response_date(row)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.survey_item_response(response_id:, survey_item:)
|
|
||||||
SurveyItemResponse.find_by(response_id:, survey_item:)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.response_id(row)
|
|
||||||
row['Response ID'] || row['ResponseId'] || row['ResponseID']
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.dese_id(row)
|
|
||||||
row['DESE ID' || 'Dese ID'] || row['DeseId'] || row['DeseID']
|
|
||||||
end
|
|
||||||
|
|
||||||
private_class_method :process_row
|
|
||||||
private_class_method :process_survey_items
|
|
||||||
private_class_method :get_survey_item_ids_from_headers
|
|
||||||
private_class_method :dese_id?
|
|
||||||
private_class_method :create_or_update_response
|
|
||||||
private_class_method :response_date
|
|
||||||
private_class_method :academic_year
|
|
||||||
private_class_method :survey_item_response
|
|
||||||
private_class_method :response_id
|
|
||||||
private_class_method :dese_id
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module StringMonkeyPatches
|
module StringMonkeyPatches
|
||||||
def integer?
|
|
||||||
to_i.to_s == self
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid_likert_score?
|
def valid_likert_score?
|
||||||
integer? and to_i.between? 1, 5
|
to_i.between? 1, 5
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,28 @@
|
||||||
<%# TODO Hook up the buttons so that only the selected races are shown for each column %>
|
|
||||||
<h3 class="sub-header-4 mt-5">Data Filters</h3>
|
<h3 class="sub-header-4 mt-5">Data Filters</h3>
|
||||||
<div class="bg-gray p-3" data-controller="analyze">
|
<div class="bg-gray p-3" data-controller="analyze">
|
||||||
<% @graphs.each do |graph| %>
|
<% @sources.first.slices.each do |slice| %>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio"
|
<input type="radio"
|
||||||
id="<%= graph.value %>"
|
id="<%= slice.slug %>"
|
||||||
class="form-check-input"
|
class="form-check-input"
|
||||||
name="graph"
|
name="slice"
|
||||||
value="<%= base_url %>"
|
value="<%= base_url %>"
|
||||||
data-action="click->analyze#refresh"
|
data-action="click->analyze#refresh"
|
||||||
<%= graph.value == @graph.value ? "checked" : "" %>>
|
<%= slice.slug == @slice.slug ? "checked" : "" %>>
|
||||||
<label for="<%= graph.value %>"><%= graph.to_s %></label>
|
<label for="<%= slice.slug %>"><%= slice.to_s %></label>
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<select id="select-group" class="mx-3 form-select" data-id="group-dropdown" data-action="analyze#refresh">
|
||||||
|
<% @groups.each do |group| %>
|
||||||
|
<option id="<%= group.slug %>" name="group-option" value="<%= base_url %>" <%= group.slug == @group.slug ? "Selected": "" %>><%= group.name %> </option>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
</select>
|
||||||
|
|
||||||
<p class="sub-header-5 mt-3 font-size-14"> Select a group </p>
|
<p class="sub-header-5 mt-3 font-size-14"> Select a group </p>
|
||||||
|
|
||||||
<% @races.each do |race | %>
|
<% @races.each do |race | %>
|
||||||
<div class="d-flex align-items-center <%= race.slug %>">
|
<div class="d-flex align-items-center">
|
||||||
<input
|
<input
|
||||||
id="<%= race.slug %>"
|
id="<%= race.slug %>"
|
||||||
class="m-3 race-checkbox form-check-input"
|
class="m-3 race-checkbox form-check-input"
|
||||||
|
|
@ -26,9 +31,33 @@
|
||||||
value="<%= base_url %>"
|
value="<%= base_url %>"
|
||||||
data-action="click->analyze#refresh"
|
data-action="click->analyze#refresh"
|
||||||
<%= @selected_races.map(&:slug).include?(race.slug) ? "checked" : "" %>
|
<%= @selected_races.map(&:slug).include?(race.slug) ? "checked" : "" %>
|
||||||
<%= @graph.value == 'students-and-teachers' ? "disabled" : "" %>>
|
<%= @graph.slug == 'students-and-teachers' ? "disabled" : "" %>
|
||||||
|
<%= @group.slug == 'race' ? "" : "hidden" %>>
|
||||||
|
|
||||||
<label for="<%= race.qualtrics_code %>"><%= race.designation %></label>
|
<label for="<%= race.qualtrics_code %>"
|
||||||
|
<%= @group.slug == 'race' ? "" : "hidden" %>>
|
||||||
|
<%= race.designation %>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% @grades.each do |grade | %>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<input
|
||||||
|
id="grade-<%= grade %>"
|
||||||
|
class="m-3 grade-checkbox form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
name="grade-checkbox"
|
||||||
|
value="<%= base_url %>"
|
||||||
|
data-action="click->analyze#refresh"
|
||||||
|
<%= @selected_grades.include?(grade) ? "checked" : "" %>
|
||||||
|
<%= @graph.slug == 'students-and-teachers' ? "disabled" : "" %>
|
||||||
|
<%= @group.slug == 'grade' ? "" : "hidden" %>>
|
||||||
|
|
||||||
|
<label for="grade-<%= grade %>"
|
||||||
|
<%= @group.slug == 'grade' ? "" : "hidden" %>>
|
||||||
|
<%= grade %>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<% content_for :title do %>
|
<% content_for :title do %>
|
||||||
<h1 class="sub-header-2 color-white m-0"> Analysis of <%= @school.name %> </h1>
|
<h1 class="sub-header-2 color-white m-0"> Analysis of <%= @school.name %> </h1>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="graph-content">
|
<div class="graph-content">
|
||||||
<div class="breadcrumbs sub-header-4">
|
<div class="breadcrumbs sub-header-4">
|
||||||
<%= @category.category_id %>:<%= @category.name %> > <%= @subcategory.subcategory_id %>:<%= @subcategory.name %>
|
<%= @category.category_id %>:<%= @category.name %> > <%= @subcategory.subcategory_id %>:<%= @subcategory.name %>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddGradeToSurveyItemResponse < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
add_column :survey_item_responses, :grade, :integer
|
||||||
|
end
|
||||||
|
end
|
||||||
18
db/migrate/20221015002312_create_scores.rb
Normal file
18
db/migrate/20221015002312_create_scores.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
class CreateScores < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
create_table :scores do |t|
|
||||||
|
t.float :average
|
||||||
|
t.boolean :meets_teacher_threshold
|
||||||
|
t.boolean :meets_student_threshold
|
||||||
|
t.boolean :meets_admin_data_threshold
|
||||||
|
t.integer :group
|
||||||
|
t.references :measure, null: false, foreign_key: true
|
||||||
|
t.references :school, null: false, foreign_key: true
|
||||||
|
t.references :academic_year, null: false, foreign_key: true
|
||||||
|
t.integer :grade
|
||||||
|
t.references :race, null: false, foreign_key: true
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddGradeIndexToSurveyItemResponse < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
add_index :survey_item_responses, [:school_id, :survey_item_id, :academic_year_id, :grade], name: "index_survey_responses_on_grade"
|
||||||
|
end
|
||||||
|
end
|
||||||
29
db/schema.rb
29
db/schema.rb
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2022_08_22_214951) do
|
ActiveRecord::Schema[7.0].define(version: 2022_10_15_023621) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "pg_stat_statements"
|
enable_extension "pg_stat_statements"
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
@ -339,7 +339,6 @@ ActiveRecord::Schema[7.0].define(version: 2022_08_22_214951) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["academic_year_id"], name: "index_response_rates_on_academic_year_id"
|
t.index ["academic_year_id"], name: "index_response_rates_on_academic_year_id"
|
||||||
t.index ["school_id", "subcategory_id"], name: "index_response_rates_on_school_id_and_subcategory_id"
|
t.index ["school_id", "subcategory_id"], name: "index_response_rates_on_school_id_and_subcategory_id"
|
||||||
t.index ["school_id"], name: "index_response_rates_on_school_id"
|
|
||||||
t.index ["subcategory_id"], name: "index_response_rates_on_subcategory_id"
|
t.index ["subcategory_id"], name: "index_response_rates_on_subcategory_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -366,6 +365,25 @@ ActiveRecord::Schema[7.0].define(version: 2022_08_22_214951) do
|
||||||
t.index ["dese_id"], name: "index_schools_on_dese_id", unique: true
|
t.index ["dese_id"], name: "index_schools_on_dese_id", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "scores", force: :cascade do |t|
|
||||||
|
t.float "average"
|
||||||
|
t.boolean "meets_teacher_threshold"
|
||||||
|
t.boolean "meets_student_threshold"
|
||||||
|
t.boolean "meets_admin_data_threshold"
|
||||||
|
t.integer "group"
|
||||||
|
t.bigint "measure_id", null: false
|
||||||
|
t.bigint "school_id", null: false
|
||||||
|
t.bigint "academic_year_id", null: false
|
||||||
|
t.integer "grade"
|
||||||
|
t.bigint "race_id", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["academic_year_id"], name: "index_scores_on_academic_year_id"
|
||||||
|
t.index ["measure_id"], name: "index_scores_on_measure_id"
|
||||||
|
t.index ["race_id"], name: "index_scores_on_race_id"
|
||||||
|
t.index ["school_id"], name: "index_scores_on_school_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "student_races", force: :cascade do |t|
|
create_table "student_races", force: :cascade do |t|
|
||||||
t.bigint "student_id", null: false
|
t.bigint "student_id", null: false
|
||||||
t.bigint "race_id", null: false
|
t.bigint "race_id", null: false
|
||||||
|
|
@ -403,10 +421,11 @@ ActiveRecord::Schema[7.0].define(version: 2022_08_22_214951) do
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.bigint "student_id"
|
t.bigint "student_id"
|
||||||
|
t.integer "grade"
|
||||||
t.index ["academic_year_id"], name: "index_survey_item_responses_on_academic_year_id"
|
t.index ["academic_year_id"], name: "index_survey_item_responses_on_academic_year_id"
|
||||||
t.index ["response_id"], name: "index_survey_item_responses_on_response_id"
|
t.index ["response_id"], name: "index_survey_item_responses_on_response_id"
|
||||||
t.index ["school_id", "academic_year_id"], name: "index_survey_item_responses_on_school_id_and_academic_year_id"
|
t.index ["school_id", "academic_year_id"], name: "index_survey_item_responses_on_school_id_and_academic_year_id"
|
||||||
t.index ["school_id"], name: "index_survey_item_responses_on_school_id"
|
t.index ["school_id", "survey_item_id", "academic_year_id", "grade"], name: "index_survey_responses_on_grade"
|
||||||
t.index ["student_id"], name: "index_survey_item_responses_on_student_id"
|
t.index ["student_id"], name: "index_survey_item_responses_on_student_id"
|
||||||
t.index ["survey_item_id"], name: "index_survey_item_responses_on_survey_item_id"
|
t.index ["survey_item_id"], name: "index_survey_item_responses_on_survey_item_id"
|
||||||
end
|
end
|
||||||
|
|
@ -457,6 +476,10 @@ ActiveRecord::Schema[7.0].define(version: 2022_08_22_214951) do
|
||||||
add_foreign_key "response_rates", "subcategories"
|
add_foreign_key "response_rates", "subcategories"
|
||||||
add_foreign_key "scales", "measures"
|
add_foreign_key "scales", "measures"
|
||||||
add_foreign_key "schools", "districts"
|
add_foreign_key "schools", "districts"
|
||||||
|
add_foreign_key "scores", "academic_years"
|
||||||
|
add_foreign_key "scores", "measures"
|
||||||
|
add_foreign_key "scores", "races"
|
||||||
|
add_foreign_key "scores", "schools"
|
||||||
add_foreign_key "student_races", "races"
|
add_foreign_key "student_races", "races"
|
||||||
add_foreign_key "student_races", "students"
|
add_foreign_key "student_races", "students"
|
||||||
add_foreign_key "subcategories", "categories"
|
add_foreign_key "subcategories", "categories"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -40,14 +40,10 @@ namespace :one_off do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task change_overall_performance_measure_id: :environment do
|
|
||||||
measure_4aii = Measure.where(name: 'Overall Performance')[0]
|
|
||||||
measure_4aii.update! measure_id: '4A-i'
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'load a single file'
|
desc 'load a single file'
|
||||||
task load_single_file: :environment do
|
task load_single_file: :environment do
|
||||||
filepath = Rails.root.join('data', 'survey_responses', '2016-17_student_survey_responses.csv')
|
filepath = Rails.root.join('data', 'survey_responses',
|
||||||
|
'2021-22_revere_somerville_wareham_student_survey_responses.csv')
|
||||||
puts "=====================> Loading data from csv at path: #{filepath}"
|
puts "=====================> Loading data from csv at path: #{filepath}"
|
||||||
SurveyResponsesDataLoader.load_data filepath: filepath
|
SurveyResponsesDataLoader.load_data filepath: filepath
|
||||||
puts "=====================> Completed loading #{SurveyItemResponse.count} survey responses"
|
puts "=====================> Completed loading #{SurveyItemResponse.count} survey responses"
|
||||||
|
|
@ -78,44 +74,6 @@ namespace :one_off do
|
||||||
puts "=====================> Completed loading #{Student.count} survey responses"
|
puts "=====================> Completed loading #{Student.count} survey responses"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'load revere somerville warehame results for 2021-22'
|
|
||||||
task load_revere: :environment do
|
|
||||||
['2021-22_revere_somerville_wareham_student_survey_responses.csv',
|
|
||||||
'2021-22_revere_somerville_wareham_teacher_survey_responses.csv'].each do |filepath|
|
|
||||||
filepath = Rails.root.join('data', 'survey_responses', filepath)
|
|
||||||
puts "=====================> Loading data from csv at path: #{filepath}"
|
|
||||||
SurveyResponsesDataLoader.load_data filepath:
|
|
||||||
end
|
|
||||||
puts 'Resetting response rates'
|
|
||||||
revere = District.find_by_name 'Revere'
|
|
||||||
somerville = District.find_by_name 'Somerville'
|
|
||||||
wareham = District.find_by_name 'Wareham'
|
|
||||||
academic_year = AcademicYear.find_by_range '2021-22'
|
|
||||||
ResponseRateLoader.reset(schools: revere.schools, academic_years: [academic_year])
|
|
||||||
ResponseRateLoader.reset(schools: somerville.schools, academic_years: [academic_year])
|
|
||||||
ResponseRateLoader.reset(schools: wareham.schools, academic_years: [academic_year])
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed recalculating #{ResponseRate.count} response rates"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'load lowell and milford results for 2021-22'
|
|
||||||
task load_lowell: :environment do
|
|
||||||
['2021-22_lowell_milford_student_survey_responses.csv',
|
|
||||||
'2021-22_lowell_milford_teacher_survey_responses.csv'].each do |filepath|
|
|
||||||
filepath = Rails.root.join('data', 'survey_responses', filepath)
|
|
||||||
puts "=====================> Loading data from csv at path: #{filepath}"
|
|
||||||
SurveyResponsesDataLoader.load_data filepath:
|
|
||||||
end
|
|
||||||
puts 'Resetting response rates'
|
|
||||||
lowell = District.find_by_name 'Lowell'
|
|
||||||
milford = District.find_by_name 'Milford'
|
|
||||||
academic_year = AcademicYear.find_by_range '2021-22'
|
|
||||||
ResponseRateLoader.reset(schools: lowell.schools, academic_years: [academic_year])
|
|
||||||
ResponseRateLoader.reset(schools: milford.schools, academic_years: [academic_year])
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed recalculating #{ResponseRate.count} response rates"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'reset race score calculations'
|
desc 'reset race score calculations'
|
||||||
task reset_race_scores_2021: :environment do
|
task reset_race_scores_2021: :environment do
|
||||||
puts 'Resetting race scores'
|
puts 'Resetting race scores'
|
||||||
|
|
@ -125,51 +83,6 @@ namespace :one_off do
|
||||||
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'reset race score calculations'
|
|
||||||
task reset_race_scores_2020: :environment do
|
|
||||||
puts 'Resetting race scores'
|
|
||||||
academic_years = [AcademicYear.find_by_range('2020-21')]
|
|
||||||
RaceScoreLoader.reset(academic_years:, fast_processing: false)
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'reset race score calculations'
|
|
||||||
task reset_race_scores_2019: :environment do
|
|
||||||
puts 'Resetting race scores'
|
|
||||||
academic_years = [AcademicYear.find_by_range('2019-20')]
|
|
||||||
RaceScoreLoader.reset(academic_years:, fast_processing: false)
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'reset race score calculations'
|
|
||||||
task reset_race_scores_2018: :environment do
|
|
||||||
puts 'Resetting race scores'
|
|
||||||
academic_years = [AcademicYear.find_by_range('2018-19')]
|
|
||||||
RaceScoreLoader.reset(academic_years:, fast_processing: false)
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'reset race score calculations'
|
|
||||||
task reset_race_scores_2017: :environment do
|
|
||||||
puts 'Resetting race scores'
|
|
||||||
academic_years = [AcademicYear.find_by_range('2017-18')]
|
|
||||||
RaceScoreLoader.reset(academic_years:, fast_processing: false)
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'reset race score calculations'
|
|
||||||
task reset_race_scores_2016: :environment do
|
|
||||||
puts 'Resetting race scores'
|
|
||||||
academic_years = [AcademicYear.find_by_range('2016-17')]
|
|
||||||
RaceScoreLoader.reset(academic_years:, fast_processing: false)
|
|
||||||
Rails.cache.clear
|
|
||||||
puts "=====================> Completed loading #{RaceScore.count} race scores"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'list scales that have no survey responses'
|
desc 'list scales that have no survey responses'
|
||||||
task list_scales_that_lack_survey_responses: :environment do
|
task list_scales_that_lack_survey_responses: :environment do
|
||||||
output = AcademicYear.all.map do |academic_year|
|
output = AcademicYear.all.map do |academic_year|
|
||||||
|
|
@ -202,24 +115,4 @@ namespace :one_off do
|
||||||
end
|
end
|
||||||
pp output
|
pp output
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'delete invalid scale'
|
|
||||||
task delete_s_grmi_scale_from_2016_17: :environment do
|
|
||||||
academic_year = AcademicYear.find_by_range '2016-17'
|
|
||||||
survey_items = SurveyItem.where('survey_item_id LIKE ?', 's-grmi%')
|
|
||||||
SurveyItemResponse.joins(:survey_item).where(academic_year:, survey_item: survey_items).delete_all
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'reset admin data values'
|
|
||||||
task reset_admin_data_values: :environment do
|
|
||||||
puts "Initial count of admin data values #{AdminDataValue.all.count}"
|
|
||||||
AdminDataValue.delete_all
|
|
||||||
puts 'Deleted all admin data values'
|
|
||||||
|
|
||||||
Dir.glob(Rails.root.join('data', 'admin_data', '*.csv')).each do |filepath|
|
|
||||||
puts "=====================> Loading data from csv at path: #{filepath}"
|
|
||||||
AdminDataLoader.load_data filepath:
|
|
||||||
end
|
|
||||||
puts "=====================> Completed loading #{AdminDataValue.count} survey responses"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
Start Date,End Date,Response Type,IP Address,Progress,Duration (in seconds),Finished,RecordedDate,ResponseId,LASID,Recipient Last Name,Recipient First Name,Recipient Email,External Data Reference,Location Latitude,Location Longitude,Distribution Channel,User Language,district,school,DESE ID,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,s-emsa-q1,s-emsa-q2,s-emsa-q3,s-tint-q1,s-tint-q2,#N/A,s-tint-q4,s-tint-q5,s-acpr-q1,s-acpr-q2,s-acpr-q3,s-acpr-q4,#N/A,#N/A,s-cure-q3,s-cure-q4,#N/A,s-sten-q2,s-sten-q3,s-sper-q1,s-sper-q2,s-sper-q3,s-sper-q4,s-civp-q1,s-civp-q2,s-civp-q3,s-civp-q4,s-grmi-q1,#N/A,#N/A,s-grmi-q4,s-appa-q1,s-appa-q2,#N/A,s-peff-q1,s-peff-q2,s-peff-q3,s-peff-q4,s-peff-q5,s-peff-q6,s-sbel-q1,s-sbel-q2,s-sbel-q3,s-sbel-q4,s-sbel-q5,s-phys-q1,s-phys-q2,s-phys-q3,s-phys-q4,s-vale-q1,#N/A,#N/A,s-vale-q4,#N/A,s-acst-q2,s-acst-q3,#N/A,#N/A,s-grit-q1,s-grit-q2,s-grit-q3,s-grit-q4,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,race,What is your race/ethnicity?(Please select all that apply) - Selected Choice
|
Start Date,End Date,Response Type,IP Address,Progress,Duration (in seconds),Finished,RecordedDate,ResponseId,LASID,Recipient Last Name,Recipient First Name,Recipient Email,External Data Reference,Location Latitude,Location Longitude,Distribution Channel,User Language,district,school,DESE ID,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,s-emsa-q1,s-emsa-q2,s-emsa-q3,s-tint-q1,s-tint-q2,#N/A,s-tint-q4,s-tint-q5,s-acpr-q1,s-acpr-q2,s-acpr-q3,s-acpr-q4,#N/A,#N/A,s-cure-q3,s-cure-q4,#N/A,s-sten-q2,s-sten-q3,s-sper-q1,s-sper-q2,s-sper-q3,s-sper-q4,s-civp-q1,s-civp-q2,s-civp-q3,s-civp-q4,s-grmi-q1,#N/A,#N/A,s-grmi-q4,s-appa-q1,s-appa-q2,#N/A,s-peff-q1,s-peff-q2,s-peff-q3,s-peff-q4,s-peff-q5,s-peff-q6,s-sbel-q1,s-sbel-q2,s-sbel-q3,s-sbel-q4,s-sbel-q5,s-phys-q1,s-phys-q2,s-phys-q3,s-phys-q4,s-vale-q1,#N/A,#N/A,s-vale-q4,#N/A,s-acst-q2,s-acst-q3,#N/A,#N/A,s-grit-q1,s-grit-q2,s-grit-q3,s-grit-q4,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,race,What is your race/ethnicity?(Please select all that apply) - Selected Choice,grade
|
||||||
2020-09-29 18:28:41,2020-09-29 18:48:28,0,73.249.89.226,6,1186,0,2020-09-30T18:48:50,student_survey_response_1,123456,,,,,,,anonymous,EN,1,8,160505,,,,dddd,4,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,some non-integer response,6,,,,5,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EN,,,,,1,888
|
2020-09-29 18:28:41,2020-09-29 18:48:28,0,73.249.89.226,6,1186,0,2020-09-30T18:48:50,student_survey_response_1,123456,,,,,,,anonymous,EN,1,8,160505,,,,dddd,4,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,some non-integer response,6,,,,5,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EN,,,,,1,888,11th
|
||||||
2021-02-23 15:12:58,2021-02-23 15:13:17,0,50.207.254.114,0,19,0,2021-02-24T15:13:19,student_survey_response_2,234567,,,,,,,anonymous,EN,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,NA,,,,,,,,,,,,,,,,,,,,,EN,,,,,"2,3,4",888
|
2021-02-23 15:12:58,2021-02-23 15:13:17,0,50.207.254.114,0,19,0,2021-02-24T15:13:19,student_survey_response_2,234567,,,,,,,anonymous,EN,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,NA,,,,,,,,,,,,,,,,,,,,,EN,,,,,"2,3,4",888,10
|
||||||
2021-03-31 9:50:19,2021-03-31 9:59:01,0,108.7.17.250,100,522,1,2021-03-31T09:59:02,student_survey_response_3,345678,,,,,42.53340149,-70.96530151,anonymous,EN,3,2,1600310,12,4,108,3300,7,1,,,,,,,,,,,,,,2,4,2,1,4,3,3,,,,,3,3,3,3,,,,,NA,,,,,,,,,3,2,3,3,2,1,3,4,1,3,3,4,4,2,4,3,3,4,3,3,3,4,3,3,3,3,3,,,,,,,,,,3,4,4,2,3,3,1,,3,,EN,Math teacher,,,,6,888
|
2021-03-31 9:50:19,2021-03-31 9:59:01,0,108.7.17.250,100,522,1,2021-03-31T09:59:02,student_survey_response_3,345678,,,,,42.53340149,-70.96530151,anonymous,EN,3,2,1600310,12,4,108,3300,7,1,,,,,,,,,,,,,,2,4,2,1,4,3,3,,,,,3,3,3,3,,,,,NA,,,,,,,,,3,2,3,3,2,1.00,3,4,1,3,3,4,4,2,4,3,3,4,3,3,3,4,3,3,3,3,3,,,,,,,,,,3,4,4,2,3,3,1,,3,,EN,Math teacher,,,,6,888,8
|
||||||
2021-03-31 9:50:09,2021-03-31 10:00:16,0,67.186.188.168,100,607,1,2021-03-31T10:00:17,student_survey_response_4,456789,,,,,42.63510132,-71.30139923,anonymous,EN,3,2,1600310,12,18,108,2064,7,1,,2,2,1,,,,,,,,,,,,,,,,,,,,,,,,,3,5,3,3,,,,,,,,,,4,4,3,4,5,1,1,5,1,3,2,4,4,1,2,1,3,2,3,3,3,4,2,5,3,4,5,5,3,3,4,3,,,,,4,4,4,4,3,5,2,,2,,EN,,,,English teacher,7,888
|
2021-03-31 9:50:09,2021-03-31 10:00:16,0,67.186.188.168,100,607,1,2021-03-31T10:00:17,student_survey_response_4,456789,,,,,42.63510132,-71.30139923,anonymous,EN,3,2,1600310,12,18,108,2064,7,1,,2,2,1,,,,,,,,,,,,,,,,,,,,,,,,,3,5,3,3,,,,,,,,,,4,4,3,4,5,1,1,5,1,3,2,4,4,1,2,1,3,2,3,3,3,4,2,5,3,4,5,5,3,3,4,3,,,,,4,4,4,4,3,5,2,,2,,EN,,,,English teacher,7,888,8
|
||||||
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_5,567890,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1600310,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8,6,7",888
|
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_5,567890,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1600310,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8,6,7",888,7
|
||||||
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_6,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1600310,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8",888
|
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_6,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1600310,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8",888,3
|
||||||
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_7,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1600310,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,,
|
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_7,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1600310,6,15,109,3710,7,1,,2.0,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,,,4
|
||||||
|
|
|
||||||
|
58
spec/models/score_spec.rb
Normal file
58
spec/models/score_spec.rb
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Score, type: :model do
|
||||||
|
let(:zones) do
|
||||||
|
Zones.new(watch_low_benchmark: 1.5, growth_low_benchmark: 2, approval_low_benchmark: 3,
|
||||||
|
ideal_low_benchmark: 4)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:warning) do
|
||||||
|
zones.warning_zone
|
||||||
|
end
|
||||||
|
let(:watch) do
|
||||||
|
zones.watch_zone
|
||||||
|
end
|
||||||
|
let(:growth) do
|
||||||
|
zones.growth_zone
|
||||||
|
end
|
||||||
|
let(:approval) do
|
||||||
|
zones.approval_zone
|
||||||
|
end
|
||||||
|
let(:ideal) do
|
||||||
|
zones.ideal_zone
|
||||||
|
end
|
||||||
|
|
||||||
|
context '.in_zone?' do
|
||||||
|
it('returns true if the score is in the warning zone') do
|
||||||
|
score = Score.new(average: 1)
|
||||||
|
expect(score.in_zone?(zone: warning)).to eq true
|
||||||
|
expect(score.in_zone?(zone: watch)).to eq false
|
||||||
|
expect(score.in_zone?(zone: growth)).to eq false
|
||||||
|
expect(score.in_zone?(zone: approval)).to eq false
|
||||||
|
expect(score.in_zone?(zone: ideal)).to eq false
|
||||||
|
end
|
||||||
|
|
||||||
|
it('returns true if the score is in the watch zone') do
|
||||||
|
score = Score.new(average: 1.5)
|
||||||
|
expect(score.in_zone?(zone: warning)).to eq true
|
||||||
|
expect(score.in_zone?(zone: watch)).to eq true
|
||||||
|
expect(score.in_zone?(zone: growth)).to eq false
|
||||||
|
expect(score.in_zone?(zone: approval)).to eq false
|
||||||
|
expect(score.in_zone?(zone: ideal)).to eq false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
context '.blank?' do
|
||||||
|
it 'returns true if the average is nil zero or not a number' do
|
||||||
|
expect(Score.new(average: 0).blank?).to eq true
|
||||||
|
expect(Score.new(average: nil).blank?).to eq true
|
||||||
|
nan = Float::NAN
|
||||||
|
expect(Score.new(average: nan).blank?).to eq true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if the average is a non-zero float' do
|
||||||
|
expect(Score.new(average: 1).blank?).to eq false
|
||||||
|
expect(Score.new(average: 0.1).blank?).to eq false
|
||||||
|
expect(Score.new(average: -0.1).blank?).to eq false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
include Analyze::Graph
|
include Analyze::Graph
|
||||||
include Analyze::Graph::Column
|
include Analyze::Graph::Column
|
||||||
describe StudentsByGroup do
|
describe StudentsByRace do
|
||||||
let(:american_indian) { create(:race, qualtrics_code: 1) }
|
let(:american_indian) { create(:race, qualtrics_code: 1) }
|
||||||
let(:asian) { create(:race, qualtrics_code: 2) }
|
let(:asian) { create(:race, qualtrics_code: 2) }
|
||||||
let(:black) { create(:race, qualtrics_code: 3) }
|
let(:black) { create(:race, qualtrics_code: 3) }
|
||||||
|
|
@ -12,11 +12,11 @@ describe StudentsByGroup do
|
||||||
context 'when initialized with a list of races' do
|
context 'when initialized with a list of races' do
|
||||||
it 'generates corresponding race columns' do
|
it 'generates corresponding race columns' do
|
||||||
races = [american_indian]
|
races = [american_indian]
|
||||||
expect(StudentsByGroup.new(races:).columns).to eq [AmericanIndian, AllStudent]
|
expect(StudentsByRace.new(races:).columns).to eq [AmericanIndian, AllStudent]
|
||||||
races = [american_indian, asian]
|
races = [american_indian, asian]
|
||||||
expect(StudentsByGroup.new(races:).columns).to eq [AmericanIndian, Asian, AllStudent]
|
expect(StudentsByRace.new(races:).columns).to eq [AmericanIndian, Asian, AllStudent]
|
||||||
races = [black, hispanic, multiracial]
|
races = [black, hispanic, multiracial]
|
||||||
expect(StudentsByGroup.new(races:).columns).to eq [Black, Hispanic, Multiracial, AllStudent]
|
expect(StudentsByRace.new(races:).columns).to eq [Black, Hispanic, Multiracial, AllStudent]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -40,7 +40,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the score is in the Ideal zone' do
|
context 'when the score is in the Ideal zone' do
|
||||||
let(:score) { Score.new(4.4, true, true) }
|
let(:score) { Score.new(average: 4.4, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
|
|
||||||
it_behaves_like 'measure_name'
|
it_behaves_like 'measure_name'
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the score is in the Approval zone' do
|
context 'when the score is in the Approval zone' do
|
||||||
let(:score) { Score.new(3.7, true, true) }
|
let(:score) { Score.new(average: 3.7, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
|
|
||||||
it_behaves_like 'measure_name'
|
it_behaves_like 'measure_name'
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the score is in the Growth zone' do
|
context 'when the score is in the Growth zone' do
|
||||||
let(:score) { Score.new(3.2, true, true) }
|
let(:score) { Score.new(average: 3.2, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
|
|
||||||
it_behaves_like 'measure_name'
|
it_behaves_like 'measure_name'
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the score is in the Watch zone' do
|
context 'when the score is in the Watch zone' do
|
||||||
let(:score) { Score.new(2.9, true, true) }
|
let(:score) { Score.new(average: 2.9, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
|
|
||||||
it_behaves_like 'measure_name'
|
it_behaves_like 'measure_name'
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the score is in the Warning zone' do
|
context 'when the score is in the Warning zone' do
|
||||||
let(:score) { Score.new(1.0, true, true) }
|
let(:score) { Score.new(average: 1.0, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
|
|
||||||
it_behaves_like 'measure_name'
|
it_behaves_like 'measure_name'
|
||||||
|
|
||||||
|
|
@ -136,7 +136,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a measure does not contain admin data items' do
|
context 'when a measure does not contain admin data items' do
|
||||||
let(:score) { Score.new(nil, false, false) }
|
let(:score) { Score.new(average: nil, meets_teacher_threshold: false, meets_student_threshold: false) }
|
||||||
|
|
||||||
it 'it does not show a partial data indicator' do
|
it 'it does not show a partial data indicator' do
|
||||||
presenter_without_admin_data = VarianceChartRowPresenter.new measure: measure_without_admin_data_items,
|
presenter_without_admin_data = VarianceChartRowPresenter.new measure: measure_without_admin_data_items,
|
||||||
|
|
@ -149,7 +149,7 @@ describe VarianceChartRowPresenter do
|
||||||
before :each do
|
before :each do
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:score) { Score.new(nil, false, false) }
|
let(:score) { Score.new(average: nil, meets_teacher_threshold: false, meets_student_threshold: false) }
|
||||||
|
|
||||||
it 'shows a partial data indicator' do
|
it 'shows a partial data indicator' do
|
||||||
measure_with_admin_data = create(
|
measure_with_admin_data = create(
|
||||||
|
|
@ -165,7 +165,7 @@ describe VarianceChartRowPresenter do
|
||||||
ideal_low_benchmark: ideal_low_benchmark
|
ideal_low_benchmark: ideal_low_benchmark
|
||||||
admin_data_presenter = VarianceChartRowPresenter.new measure: measure_with_admin_data,
|
admin_data_presenter = VarianceChartRowPresenter.new measure: measure_with_admin_data,
|
||||||
score: Score.new(
|
score: Score.new(
|
||||||
3.7, true, true
|
average: 3.7, meets_teacher_threshold: true, meets_student_threshold: true
|
||||||
)
|
)
|
||||||
expect(admin_data_presenter.show_partial_data_indicator?).to be true
|
expect(admin_data_presenter.show_partial_data_indicator?).to be true
|
||||||
expect(admin_data_presenter.partial_data_sources).to eq ['administrative data']
|
expect(admin_data_presenter.partial_data_sources).to eq ['administrative data']
|
||||||
|
|
@ -179,7 +179,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there are insufficient teacher survey item responses' do
|
context 'when there are insufficient teacher survey item responses' do
|
||||||
let(:score) { Score.new(nil, false, true) }
|
let(:score) { Score.new(average: nil, meets_teacher_threshold: false, meets_student_threshold: true) }
|
||||||
it 'shows a partial data indicator' do
|
it 'shows a partial data indicator' do
|
||||||
expect(presenter.show_partial_data_indicator?).to be true
|
expect(presenter.show_partial_data_indicator?).to be true
|
||||||
expect(presenter.partial_data_sources).to eq ['teacher survey results']
|
expect(presenter.partial_data_sources).to eq ['teacher survey results']
|
||||||
|
|
@ -187,7 +187,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there are sufficient teacher survey item responses' do
|
context 'when there are sufficient teacher survey item responses' do
|
||||||
let(:score) { Score.new(nil, true, true) }
|
let(:score) { Score.new(average: nil, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
it 'does not show a partial data indicator' do
|
it 'does not show a partial data indicator' do
|
||||||
expect(presenter.show_partial_data_indicator?).to be false
|
expect(presenter.show_partial_data_indicator?).to be false
|
||||||
end
|
end
|
||||||
|
|
@ -201,7 +201,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there are insufficient student survey item responses' do
|
context 'when there are insufficient student survey item responses' do
|
||||||
let(:score) { Score.new(nil, true, false) }
|
let(:score) { Score.new(average: nil, meets_teacher_threshold: true, meets_student_threshold: false) }
|
||||||
it 'shows a partial data indicator' do
|
it 'shows a partial data indicator' do
|
||||||
expect(presenter.show_partial_data_indicator?).to be true
|
expect(presenter.show_partial_data_indicator?).to be true
|
||||||
expect(presenter.partial_data_sources).to eq ['student survey results']
|
expect(presenter.partial_data_sources).to eq ['student survey results']
|
||||||
|
|
@ -220,7 +220,7 @@ describe VarianceChartRowPresenter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'When there are sufficient student survey item responses' do
|
context 'When there are sufficient student survey item responses' do
|
||||||
let(:score) { Score.new(nil, true, true) }
|
let(:score) { Score.new(average: nil, meets_teacher_threshold: true, meets_student_threshold: true) }
|
||||||
it 'does not show a partial data indicator' do
|
it 'does not show a partial data indicator' do
|
||||||
expect(presenter.show_partial_data_indicator?).to be false
|
expect(presenter.show_partial_data_indicator?).to be false
|
||||||
end
|
end
|
||||||
|
|
@ -236,15 +236,15 @@ describe VarianceChartRowPresenter do
|
||||||
growth_low_benchmark:,
|
growth_low_benchmark:,
|
||||||
approval_low_benchmark:,
|
approval_low_benchmark:,
|
||||||
ideal_low_benchmark:)
|
ideal_low_benchmark:)
|
||||||
approval_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(3.7, true, true)
|
approval_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(average: 3.7, meets_teacher_threshold: true,meets_student_threshold: true)
|
||||||
ideal_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(4.4, true, true)
|
ideal_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(average: 4.4, meets_teacher_threshold: true, meets_student_threshold: true)
|
||||||
expect(ideal_presenter <=> approval_presenter).to be < 0
|
expect(ideal_presenter <=> approval_presenter).to be < 0
|
||||||
expect([approval_presenter, ideal_presenter].sort).to eq [ideal_presenter, approval_presenter]
|
expect([approval_presenter, ideal_presenter].sort).to eq [ideal_presenter, approval_presenter]
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'selects a warning bar below a ideal bar' do
|
it 'selects a warning bar below a ideal bar' do
|
||||||
warning_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(1.0, true, true)
|
warning_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(average: 1.0, meets_teacher_threshold: true, meets_student_threshold: true)
|
||||||
ideal_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(5.0, true, true)
|
ideal_presenter = VarianceChartRowPresenter.new measure: measure, score: Score.new(average: 5.0, meets_teacher_threshold: true, meets_student_threshold: true)
|
||||||
expect(warning_presenter <=> ideal_presenter).to be > 0
|
expect(warning_presenter <=> ideal_presenter).to be > 0
|
||||||
expect([warning_presenter, ideal_presenter].sort).to eq [ideal_presenter, warning_presenter]
|
expect([warning_presenter, ideal_presenter].sort).to eq [ideal_presenter, warning_presenter]
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,10 @@ describe SurveyResponsesDataLoader do
|
||||||
end
|
end
|
||||||
it 'ensures teacher responses load correctly' do
|
it 'ensures teacher responses load correctly' do
|
||||||
assigns_academic_year_to_survey_item_responses
|
assigns_academic_year_to_survey_item_responses
|
||||||
|
|
||||||
assigns_school_to_the_survey_item_responses
|
assigns_school_to_the_survey_item_responses
|
||||||
|
|
||||||
loads_survey_item_responses_for_a_given_survey_response
|
loads_survey_item_responses_for_a_given_survey_response
|
||||||
|
|
||||||
loads_all_survey_item_responses_for_a_given_survey_item
|
loads_all_survey_item_responses_for_a_given_survey_item
|
||||||
|
|
||||||
captures_likert_scores_for_survey_item_responses
|
captures_likert_scores_for_survey_item_responses
|
||||||
|
|
||||||
is_idempotent
|
is_idempotent
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -53,16 +48,23 @@ describe SurveyResponsesDataLoader do
|
||||||
loads_student_survey_item_response_values
|
loads_student_survey_item_response_values
|
||||||
student_survey_item_response_count_matches_expected
|
student_survey_item_response_count_matches_expected
|
||||||
captures_likert_scores_for_student_survey_item_responses
|
captures_likert_scores_for_student_survey_item_responses
|
||||||
|
assigns_grade_level_to_responses
|
||||||
is_idempotent_for_students
|
is_idempotent_for_students
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when updating student survey responses from another csv file' do
|
context 'when updating student survey responses from another csv file' do
|
||||||
it 'updates the likert score to the score on the new csv file' do
|
before do
|
||||||
SurveyResponsesDataLoader.load_data filepath: Rails.root.join('spec', 'fixtures',
|
SurveyResponsesDataLoader.load_data filepath: Rails.root.join('spec', 'fixtures',
|
||||||
'secondary_test_2020-21_student_survey_responses.csv')
|
'secondary_test_2020-21_student_survey_responses.csv')
|
||||||
expect(SurveyItemResponse.joins(:survey_item).where(response_id: 'student_survey_response_3').where("survey_item.survey_item_id": 's-emsa-q1').first.likert_score).to eq 1
|
end
|
||||||
expect(SurveyItemResponse.joins(:survey_item).where(response_id: 'student_survey_response_4').where("survey_item.survey_item_id": 's-emsa-q1').first.likert_score).to eq 1
|
it 'updates the likert score to the score on the new csv file' do
|
||||||
expect(SurveyItemResponse.joins(:survey_item).where(response_id: 'student_survey_response_5').where("survey_item.survey_item_id": 's-emsa-q1').first.likert_score).to eq 1
|
s_emsa_q1 = SurveyItem.find_by_survey_item_id 's-emsa-q1'
|
||||||
|
expect(SurveyItemResponse.where(response_id: 'student_survey_response_3',
|
||||||
|
survey_item: s_emsa_q1).first.likert_score).to eq 1
|
||||||
|
expect(SurveyItemResponse.where(response_id: 'student_survey_response_4',
|
||||||
|
survey_item: s_emsa_q1).first.likert_score).to eq 1
|
||||||
|
expect(SurveyItemResponse.where(response_id: 'student_survey_response_5',
|
||||||
|
survey_item: s_emsa_q1).first.likert_score).to eq 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -160,3 +162,17 @@ def is_idempotent_for_students
|
||||||
|
|
||||||
expect(SurveyItemResponse.count).to eq number_of_survey_item_responses
|
expect(SurveyItemResponse.count).to eq number_of_survey_item_responses
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assigns_grade_level_to_responses
|
||||||
|
results = { 'student_survey_response_1' => 11,
|
||||||
|
'student_survey_response_3' => 8,
|
||||||
|
'student_survey_response_4' => 8,
|
||||||
|
'student_survey_response_5' => 7,
|
||||||
|
'student_survey_response_6' => 3,
|
||||||
|
'student_survey_response_7' => 4 }
|
||||||
|
results.each do |key, value|
|
||||||
|
expect(SurveyItemResponse.where(response_id: key).all? do |response|
|
||||||
|
response.grade == value
|
||||||
|
end).to eq true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ describe 'analyze/index' do
|
||||||
end
|
end
|
||||||
let(:graph) { StudentsAndTeachers.new }
|
let(:graph) { StudentsAndTeachers.new }
|
||||||
let(:graphs) do
|
let(:graphs) do
|
||||||
[StudentsAndTeachers.new, StudentsByGroup.new(races:)]
|
[StudentsAndTeachers.new, StudentsByRace.new(races:)]
|
||||||
end
|
end
|
||||||
let(:background) { BackgroundPresenter.new(num_of_columns: graph.columns.count) }
|
let(:background) { BackgroundPresenter.new(num_of_columns: graph.columns.count) }
|
||||||
let(:selected_races) { races }
|
let(:selected_races) { races }
|
||||||
|
|
@ -54,6 +54,36 @@ describe 'analyze/index' do
|
||||||
measure
|
measure
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let(:sources) do
|
||||||
|
[Analyze::Source::SurveyData.new(slices:)]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:slices) do
|
||||||
|
students_and_teachers = Analyze::Slice::StudentsAndTeachers.new
|
||||||
|
students_by_group = Analyze::Slice::StudentsByGroup.new(races:, grades:)
|
||||||
|
[students_and_teachers, students_by_group]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:slice) do
|
||||||
|
slices.first
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:groups) do
|
||||||
|
[Analyze::Group::Race.new, Analyze::Group::Grade.new]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:group) do
|
||||||
|
groups.first
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:grades) do
|
||||||
|
(1..12).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:selected_grades) do
|
||||||
|
grades
|
||||||
|
end
|
||||||
|
|
||||||
before :each do
|
before :each do
|
||||||
assign :races, races
|
assign :races, races
|
||||||
assign :selected_races, selected_races
|
assign :selected_races, selected_races
|
||||||
|
|
@ -70,6 +100,12 @@ describe 'analyze/index' do
|
||||||
assign :subcategory, subcategory
|
assign :subcategory, subcategory
|
||||||
assign :subcategories, category.subcategories
|
assign :subcategories, category.subcategories
|
||||||
assign :measures, [support_for_teaching, effective_leadership, professional_qualifications]
|
assign :measures, [support_for_teaching, effective_leadership, professional_qualifications]
|
||||||
|
assign :sources, sources
|
||||||
|
assign :groups, groups
|
||||||
|
assign :group, group
|
||||||
|
assign :slice, slice
|
||||||
|
assign :grades, grades
|
||||||
|
assign :selected_grades, selected_grades
|
||||||
create(:respondent, school:, academic_year:)
|
create(:respondent, school:, academic_year:)
|
||||||
create(:survey, school:, academic_year:)
|
create(:survey, school:, academic_year:)
|
||||||
end
|
end
|
||||||
|
|
@ -88,7 +124,7 @@ describe 'analyze/index' do
|
||||||
# ideal_low_benchmark: 4.5)
|
# ideal_low_benchmark: 4.5)
|
||||||
# [
|
# [
|
||||||
# GroupedBarColumnPresenter.new(measure:,
|
# GroupedBarColumnPresenter.new(measure:,
|
||||||
# score: Score.new(rand))
|
# score: Score.new(average: rand))
|
||||||
# ]
|
# ]
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ describe 'overview/index' do
|
||||||
let(:variance_chart_row_presenters) do
|
let(:variance_chart_row_presenters) do
|
||||||
[
|
[
|
||||||
VarianceChartRowPresenter.new(measure: support_for_teaching, score: Score.new),
|
VarianceChartRowPresenter.new(measure: support_for_teaching, score: Score.new),
|
||||||
VarianceChartRowPresenter.new(measure: effective_leadership, score: Score.new(rand)),
|
VarianceChartRowPresenter.new(measure: effective_leadership, score: Score.new(average: rand)),
|
||||||
VarianceChartRowPresenter.new(measure: professional_qualifications, score: Score.new)
|
VarianceChartRowPresenter.new(measure: professional_qualifications, score: Score.new)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
@ -90,7 +90,7 @@ describe 'overview/index' do
|
||||||
ideal_low_benchmark: 4.5)
|
ideal_low_benchmark: 4.5)
|
||||||
[
|
[
|
||||||
VarianceChartRowPresenter.new(measure:,
|
VarianceChartRowPresenter.new(measure:,
|
||||||
score: Score.new(rand))
|
score: Score.new(average: rand))
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ describe 'overview/_variance_chart.html.erb' do
|
||||||
|
|
||||||
before :each do
|
before :each do
|
||||||
presenters = [
|
presenters = [
|
||||||
VarianceChartRowPresenter.new(measure: lower_scoring_measure, score: Score.new(1)),
|
VarianceChartRowPresenter.new(measure: lower_scoring_measure, score: Score.new(average: 1)),
|
||||||
VarianceChartRowPresenter.new(measure: higher_scoring_measure, score: Score.new(5))
|
VarianceChartRowPresenter.new(measure: higher_scoring_measure, score: Score.new(average: 5))
|
||||||
]
|
]
|
||||||
|
|
||||||
render partial: 'variance_chart', locals: { presenters: }
|
render partial: 'variance_chart', locals: { presenters: }
|
||||||
|
|
@ -53,8 +53,8 @@ describe 'overview/_variance_chart.html.erb' do
|
||||||
measure_lacking_score = create(:measure)
|
measure_lacking_score = create(:measure)
|
||||||
another_measure_lacking_score = create(:measure)
|
another_measure_lacking_score = create(:measure)
|
||||||
presenters = [
|
presenters = [
|
||||||
VarianceChartRowPresenter.new(measure: measure_lacking_score, score: Score.new(nil)),
|
VarianceChartRowPresenter.new(measure: measure_lacking_score, score: Score.new(average: nil)),
|
||||||
VarianceChartRowPresenter.new(measure: another_measure_lacking_score, score: Score.new(nil))
|
VarianceChartRowPresenter.new(measure: another_measure_lacking_score, score: Score.new(average: nil))
|
||||||
]
|
]
|
||||||
|
|
||||||
render partial: 'variance_chart', locals: { presenters: }
|
render partial: 'variance_chart', locals: { presenters: }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue