You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sqm-dashboards/app/models/report/measure.rb

127 lines
4.9 KiB

module Report
class Measure
def self.create_report(schools: School.all.includes(:district), academic_years: AcademicYear.all, measures: ::Measure.all, filename: "measure_report.csv")
data = to_csv(schools, academic_years:, measures:)
FileUtils.mkdir_p Rails.root.join("tmp", "reports")
filepath = Rails.root.join("tmp", "reports", filename)
write_csv(data:, filepath:)
data
end
def self.to_csv(schools:, academic_years:, measures:)
data = []
mutex = Thread::Mutex.new
data << ["Measure Name", "Measure ID", "District", "School", "School Code", "Academic Year", "Recorded Date Range", "Grades", "Student Score", "Student Zone", "Teacher Score",
"Teacher Zone", "Admin Score", "Admin Zone", "All Score (Average)", "All Score Zone"]
pool_size = 2
jobs = Queue.new
schools.each { |school| jobs << school }
workers = pool_size.times.map do
Thread.new do
while school = jobs.pop(true)
academic_years.each do |academic_year|
respondents = Respondent.by_school_and_year(school:, academic_year:)
next if respondents.nil?
begin_date = ::SurveyItemResponse.where(school:,
academic_year:).where.not(recorded_date: nil).order(:recorded_date).first&.recorded_date&.to_date
end_date = ::SurveyItemResponse.where(school:,
academic_year:).where.not(recorded_date: nil).order(:recorded_date).last&.recorded_date&.to_date
date_range = "#{begin_date} - #{end_date}"
all_grades = Respondent.grades_that_responded_to_survey(academic_year: academic_year, school: school)
grades = "#{all_grades.first}-#{all_grades.last}"
measures.each do |measure|
score = measure.score(school:, academic_year:)
zone = measure.zone(school:, academic_year:).type.to_s.capitalize
response_rate = measure.subcategory.response_rate(school:, academic_year:)
next unless response_rate.meets_student_threshold? || response_rate.meets_teacher_threshold?
row = [response_rate, measure, school, academic_year]
mutex.synchronize do
data << [measure.name,
measure.measure_id,
school.district.name,
school.name,
school.dese_id,
academic_year.range,
date_range,
grades,
student_score(row:),
student_zone(row:),
teacher_score(row:),
teacher_zone(row:),
admin_score(row:),
admin_zone(row:),
score.average,
zone]
end
end
end
end
rescue ThreadError
end
end
workers.each(&:join)
csv = CSV.generate do |csv|
data.each do |row|
csv << row
end
end
end
def self.write_csv(data:, filepath:)
File.write(filepath, csv)
end
def self.student_score(row:)
row in [response_rate, measure, school, academic_year]
student_score = measure.student_score(school:, academic_year:).average if response_rate.meets_student_threshold?
student_score || "N/A"
end
def self.student_zone(row:)
row in [response_rate, measure, school, academic_year]
if response_rate.meets_student_threshold?
student_zone = measure.student_zone(school:,
academic_year:).type.to_s.capitalize
end
student_zone || "N/A"
end
def self.teacher_score(row:)
row in [response_rate, measure, school, academic_year]
teacher_score = measure.teacher_score(school:, academic_year:).average if response_rate.meets_teacher_threshold?
teacher_score || "N/A"
end
def self.teacher_zone(row:)
row in [response_rate, measure, school, academic_year]
if response_rate.meets_teacher_threshold?
teacher_zone = measure.teacher_zone(school:, academic_year:).type.to_s.capitalize
end
teacher_zone || "N/A"
end
def self.admin_score(row:)
row in [response_rate, measure, school, academic_year]
admin_score = measure.admin_score(school:, academic_year:).average
admin_score = "N/A" unless admin_score.present? && admin_score >= 0
admin_score
end
def self.admin_zone(row:)
row in [response_rate, measure, school, academic_year]
tmp_zone = measure.admin_zone(school:, academic_year:).type
tmp_zone == :insufficient_data ? "N/A" : tmp_zone.to_s.capitalize
end
end
end