If the measure is not based on a type of data(student/teacher) or if there is insufficent data to calculate a score, show a message on the graph indicating such

pull/1/head
Nelson Jovel 4 years ago
parent 3d7e62f21f
commit 9837fbf0d0

@ -6,7 +6,7 @@ class AnalyzeController < SqmApplicationController
@subcategory ||= Subcategory.find_by_subcategory_id(params[:subcategory_id]) @subcategory ||= Subcategory.find_by_subcategory_id(params[:subcategory_id])
@subcategory ||= Subcategory.find_by_subcategory_id('1A') @subcategory ||= Subcategory.find_by_subcategory_id('1A')
@measure = @subcategory.measures.includes(%i[admin_data_items category])[0] @measure = @subcategory.measures.order(:measure_id).includes(%i[admin_data_items category])[0]
@academic_year ||= AcademicYear.order('range DESC').first @academic_year ||= AcademicYear.order('range DESC').first
end end
end end

@ -4,7 +4,7 @@ class GroupedBarColumnPresenter
def initialize(measure:, score:, position:, type:) def initialize(measure:, score:, position:, type:)
@measure = measure @measure = measure
@score = score.average @score = score
@meets_teacher_threshold = score.meets_teacher_threshold? @meets_teacher_threshold = score.meets_teacher_threshold?
@meets_student_threshold = score.meets_student_threshold? @meets_student_threshold = score.meets_student_threshold?
@measure_name = @measure.name @measure_name = @measure.name
@ -45,7 +45,7 @@ class GroupedBarColumnPresenter
end end
def percentage def percentage
(@score - zone.low_benchmark) / (zone.high_benchmark - zone.low_benchmark) (@score.average - zone.low_benchmark) / (zone.high_benchmark - zone.low_benchmark)
end end
def zone def zone
@ -55,7 +55,7 @@ class GroupedBarColumnPresenter
approval_low_benchmark: @measure.approval_low_benchmark, approval_low_benchmark: @measure.approval_low_benchmark,
ideal_low_benchmark: @measure.ideal_low_benchmark ideal_low_benchmark: @measure.ideal_low_benchmark
) )
zones.zone_for_score(@score) zones.zone_for_score(@score.average)
end end
def label def label
@ -68,4 +68,26 @@ class GroupedBarColumnPresenter
'All Teachers' 'All Teachers'
end end
end end
def show_irrelevancy_message?
return true if type == :student && !@measure.includes_student_survey_items?
return true if type == :teacher && !@measure.includes_teacher_survey_items?
return true if type == :all && !@measure.includes_teacher_survey_items? && !@measure.includes_student_survey_items?
false
end
def show_insufficient_data_message?
case type
when :all
!score.meets_teacher_threshold? && !score.meets_student_threshold?
when :student
!score.meets_student_threshold?
when :teacher
!score.meets_teacher_threshold?
else
false
end
end
end end

@ -2,10 +2,27 @@
<rect x="<%= bar_label_x(presenter.position) - 2.5 %>%" y="<%= presenter.y_offset %>%" width="5%" height="<%= presenter.bar_height_percentage %>%" fill="#3E3A38" data-for-measure-id="<%= presenter.measure_id %>"/> <rect x="<%= bar_label_x(presenter.position) - 2.5 %>%" y="<%= presenter.y_offset %>%" width="5%" height="<%= presenter.bar_height_percentage %>%" fill="#3E3A38" data-for-measure-id="<%= presenter.measure_id %>"/>
<text x="<%= bar_label_x(presenter.position) %>%" y="<%= 5 %>%" text-anchor="middle" dominant-baseline="middle" > <text x="<%= bar_label_x(presenter.position) %>%" y="<%= 5 %>%" text-anchor="middle" dominant-baseline="middle" >
<%= presenter.score %> <%= presenter.score.average %>
</text> </text>
<text class="graph-footer" x="<%= bar_label_x(presenter.position) %>%" y="<%= bar_label_height %>%" text-anchor="middle" dominant-baseline="middle" data-grouped-bar-label="<%= presenter.label %>"> <text class="graph-footer" x="<%= bar_label_x(presenter.position) %>%" y="<%= bar_label_height %>%" text-anchor="middle" dominant-baseline="middle" data-grouped-bar-label="<%= presenter.label %>">
<%= presenter.label %> <%= presenter.label %>
</text> </text>
<% if presenter.show_irrelevancy_message? %>
<rect x="<%= bar_label_x(presenter.position) - 10 %>%" y="<%= 17 %>%" rx="15" ry="15" width="20%" height="<%= 34 %>%" fill="white" stroke="gray"/>
<text x="<%= bar_label_x(presenter.position) %>%" y="<%= 20 %>%" text-anchor="middle">
<tspan x="<%= bar_label_x(presenter.position) %>%" y="29%">measure not</tspan>
<tspan x="<%= bar_label_x(presenter.position) %>%" y="34%">based on </tspan>
<tspan x="<%= bar_label_x(presenter.position) %>%" y="39%"><%= presenter.type %> surveys </tspan>
</text>
<% elsif presenter.show_insufficient_data_message? %>
<rect x="<%= bar_label_x(presenter.position) - 10 %>%" y="<%= 17 %>%" rx="15" ry="15" width="20%" height="<%= 34 %>%" fill="white" stroke="gray" />
<text x="<%= bar_label_x(presenter.position) %>%" y="<%= 20 %>%" text-anchor="middle" >
<tspan x="<%= bar_label_x(presenter.position) %>%" y="29%">survey response</tspan>
<tspan x="<%= bar_label_x(presenter.position) %>%" y="34%">rate below 25%</tspan>
</text>
<% end %>
</g> </g>

@ -6,7 +6,7 @@ describe GroupedBarColumnPresenter do
let(:approval_low_benchmark) { 3.6 } let(:approval_low_benchmark) { 3.6 }
let(:ideal_low_benchmark) { 3.8 } let(:ideal_low_benchmark) { 3.8 }
let(:measure) do let(:measure_with_student_survey_items) do
measure = create( measure = create(
:measure, :measure,
name: 'Some Title' name: 'Some Title'
@ -22,6 +22,21 @@ describe GroupedBarColumnPresenter do
measure measure
end end
let(:measure_with_teacher_survey_items) do
measure = create(
:measure,
name: 'Some Title'
)
scale = create(:scale, measure:)
create(:teacher_survey_item, scale:,
watch_low_benchmark:,
growth_low_benchmark:,
approval_low_benchmark:,
ideal_low_benchmark:)
measure
end
let(:measure_without_admin_data_items) do let(:measure_without_admin_data_items) do
create( create(
:measure, :measure,
@ -29,159 +44,165 @@ describe GroupedBarColumnPresenter do
) )
end end
let(:presenter) do let(:student_presenter) do
GroupedBarColumnPresenter.new measure:, score:, position: 1, type: :all GroupedBarColumnPresenter.new measure: measure_with_student_survey_items, score:, position: 1, type: :student
end
let(:teacher_presenter) do
GroupedBarColumnPresenter.new measure: measure_with_teacher_survey_items, score:, position: 1, type: :teacher
end end
shared_examples_for 'measure_name' do shared_examples_for 'measure_name' do
it 'returns the measure name' do it 'returns the measure name' do
expect(presenter.measure_name).to eq 'Some Title' expect(student_presenter.measure_name).to eq 'Some Title'
end end
end end
context 'when the score is in the Ideal zone' do context 'when a measure is based on student survey items' do
let(:score) { Score.new(4.4, true, true) } context 'when the score is in the Ideal zone' do
let(:score) { Score.new(4.4, true, true) }
it_behaves_like 'measure_name' it_behaves_like 'measure_name'
it 'returns the correct color' do it 'returns the correct color' do
expect(presenter.bar_color).to eq 'fill-ideal' expect(student_presenter.bar_color).to eq 'fill-ideal'
end end
it 'returns a bar width equal to the approval zone width plus the proportionate ideal zone width' do it 'returns a bar width equal to the approval zone width plus the proportionate ideal zone width' do
expect(presenter.bar_height_percentage).to be_within(0.01).of(25.5) expect(student_presenter.bar_height_percentage).to be_within(0.01).of(25.5)
end end
it 'returns a y_offset equal to the ' do it 'returns a y_offset equal to the ' do
expect(presenter.y_offset).to be_within(0.01).of(8.5) expect(student_presenter.y_offset).to be_within(0.01).of(8.5)
end
end 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(3.7, true, true) }
it_behaves_like 'measure_name' it_behaves_like 'measure_name'
it 'returns the correct color' do it 'returns the correct color' do
expect(presenter.bar_color).to eq 'fill-approval' expect(student_presenter.bar_color).to eq 'fill-approval'
end end
it 'returns a bar width equal to the proportionate approval zone width' do it 'returns a bar width equal to the proportionate approval zone width' do
expect(presenter.bar_height_percentage).to be_within(0.01).of(8.5) expect(student_presenter.bar_height_percentage).to be_within(0.01).of(8.5)
end end
it 'returns an x-offset of 60%' do it 'returns an x-offset of 60%' do
expect(presenter.y_offset).to be_within(0.01).of(25.5) expect(student_presenter.y_offset).to be_within(0.01).of(25.5)
end
end 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(3.2, true, true) }
it_behaves_like 'measure_name' it_behaves_like 'measure_name'
it 'returns the correct color' do it 'returns the correct color' do
expect(presenter.bar_color).to eq 'fill-growth' expect(student_presenter.bar_color).to eq 'fill-growth'
end end
it 'returns a bar width equal to the proportionate growth zone width' do
expect(student_presenter.bar_height_percentage).to be_within(0.01).of(13.59)
end
it 'returns a bar width equal to the proportionate growth zone width' do context 'in order to achieve the visual effect' do
expect(presenter.bar_height_percentage).to be_within(0.01).of(13.59) it 'returns an x-offset equal to 60% minus the bar width' do
expect(student_presenter.y_offset).to eq 34
end
end
end end
context 'in order to achieve the visual effect' do context 'when the score is in the Watch zone' do
it 'returns an x-offset equal to 60% minus the bar width' do let(:score) { Score.new(2.9, true, true) }
expect(presenter.y_offset).to eq 34
it_behaves_like 'measure_name'
it 'returns the correct color' do
expect(student_presenter.bar_color).to eq 'fill-watch'
end
it 'returns a bar width equal to the proportionate watch zone width plus the growth zone width' do
expect(student_presenter.bar_height_percentage).to eq 34
end
context 'in order to achieve the visual effect' do
it 'returns an x-offset equal to 60% minus the bar width' do
expect(student_presenter.y_offset).to eq 34
end
end end
end end
end
context 'when the score is in the Watch zone' do context 'when the score is in the Warning zone' do
let(:score) { Score.new(2.9, true, true) } let(:score) { Score.new(1.0, true, true) }
it_behaves_like 'measure_name' it_behaves_like 'measure_name'
it 'returns the correct color' do it 'returns the correct color' do
expect(presenter.bar_color).to eq 'fill-watch' expect(student_presenter.bar_color).to eq 'fill-warning'
end
it 'returns a bar width equal to the proportionate warning zone width plus the watch & growth zone widths' do
expect(student_presenter.bar_height_percentage).to eq 51
end
context 'in order to achieve the visual effect' do
it 'returns an y-offset equal to 60% minus the bar width' do
expect(student_presenter.y_offset).to eq 34
end
end
end end
it 'returns a bar width equal to the proportionate watch zone width plus the growth zone width' do context 'when there are insufficient responses to calculate a score' do
expect(presenter.bar_height_percentage).to eq 34 let(:score) { Score.new(nil, true, false) }
it 'indicates it should show the insufficient data message' do
expect(student_presenter.show_insufficient_data_message?).to eq true
end
end end
context 'when there are enough responses to calculate a score' do
let(:score) { Score.new(nil, true, true) }
context 'in order to achieve the visual effect' do it 'indicates it should show the insufficient data message' do
it 'returns an x-offset equal to 60% minus the bar width' do expect(student_presenter.show_insufficient_data_message?).to eq false
expect(presenter.y_offset).to eq 34
end end
end end
end end
context 'when the presenter type is student but the measure is not based on student surveys' do
let(:score) { Score.new(nil, false, false) }
let(:student_presenter) do
GroupedBarColumnPresenter.new measure: measure_without_admin_data_items, score:, position: 1, type: :student
end
it 'indecates it should show the irrelevancy message' do
expect(student_presenter.show_irrelevancy_message?).to be true
end
end
context 'when the score is in the Warning zone' do context 'when the measure is based on teacher survey items' do
let(:score) { Score.new(1.0, true, true) } context 'when there are insufficient responses to calculate a score' do
let(:score) { Score.new(nil, false, true) }
it_behaves_like 'measure_name'
it 'returns the correct color' do it 'indicates it should show the insufficient data message' do
expect(presenter.bar_color).to eq 'fill-warning' expect(teacher_presenter.show_insufficient_data_message?).to eq true
end
end end
context 'when there are enough responses to calculate a score' do
let(:score) { Score.new(nil, true, true) }
it 'returns a bar width equal to the proportionate warning zone width plus the watch & growth zone widths' do it 'indicates it should show the insufficient data message' do
expect(presenter.bar_height_percentage).to eq 51 expect(teacher_presenter.show_insufficient_data_message?).to eq false
end
end end
context 'when the presenter type is teacher but the measure is not based on teacher surveys' do
context 'in order to achieve the visual effect' do let(:score) { Score.new(nil, false, false) }
it 'returns an y-offset equal to 60% minus the bar width' do let(:teacher_presenter) do
expect(presenter.y_offset).to eq 34 GroupedBarColumnPresenter.new measure: measure_without_admin_data_items, score:, position: 1, type: :teacher
end
it 'indecates it should show the irrelevancy message' do
expect(teacher_presenter.show_irrelevancy_message?).to be true
end end
end end
end end
# context 'when a measure contains teacher survey items' do
# before :each do
# scale = create(:scale, measure:)
# create :teacher_survey_item, scale:
# end
# context 'when there are insufficient teacher survey item responses' do
# let(:score) { Score.new(nil, false, true) }
# it 'shows a message saying there are insufficient responses' do
# expect(presenter.insufficient_teacher_responses?).to be true
# end
# end
# context 'when there are sufficient teacher survey item responses' do
# let(:score) { Score.new(nil, true, true) }
# it 'does not show a partial data indicator' do
# expect(presenter.show_teacher_inapplicability_message?).to be true
# end
# end
# end
# context 'when a measure does not contain teacher survey items' do
# context 'when there are insufficient teacher survey item responses' do
# let(:score) { Score.new(nil, false, true) }
# it 'shows a message saying the measure is not based on teacher survey items' do
# expect(presenter.show_teacher_inapplicability_message?).to be false
# end
# end
# end
# context 'when a measure contains student survey items' do
# before :each do
# scale = create(:scale, measure:)
# create :student_survey_item, scale:
# end
# context 'when there are insufficient student survey item responses' do
# let(:score) { Score.new(nil, true, false) }
# it 'shows a partial data indicator' do
# expect(presenter.show_student_inapplicability_message?).to be true
# end
# end
# context 'when there are sufficient student survey item responses' do
# let(:score) { Score.new(nil, true, true) }
# it 'shows a partial data indicator' do
# expect(presenter.show_student_inapplicability_message?).to be true
# end
# end
# end
end end

Loading…
Cancel
Save