Create construct graph svg with hard-coded parameters

pull/1/head
Alex Basson 4 years ago
parent 3b0c4c188c
commit c5bd1a9b3f

@ -3,6 +3,9 @@ class DashboardController < ApplicationController
def index
authenticate(district.name.downcase, "#{district.name.downcase}!")
@construct_graph_row_presenters = [
ConstructGraphRowPresenter.new(construct: professional_qualifications_construct, score: 4.8)
]
end
private
@ -16,7 +19,11 @@ class DashboardController < ApplicationController
end
def district
@school.district
@district ||= @school.district
end
end
def professional_qualifications_construct
Construct.new title: "Professional Qualifications", watch_low_benchmark: 2.48, growth_low_benchmark: 2.99, approval_low_benchmark: 3.49, ideal_low_benchmark: 4.7
end
end

@ -0,0 +1,33 @@
class Construct
Zone = Struct.new(:low_benchmark, :high_benchmark, :type) do
def includes_score?(score)
score > low_benchmark and score < high_benchmark
end
end
attr_reader :title, :warning_zone, :watch_zone, :growth_zone, :approval_zone, :ideal_zone
def initialize(title:, watch_low_benchmark:, growth_low_benchmark:, approval_low_benchmark:, ideal_low_benchmark:)
@title = title
@warning_zone = Zone.new(1, watch_low_benchmark, :warning)
@watch_zone = Zone.new(watch_low_benchmark, growth_low_benchmark, :watch)
@growth_zone = Zone.new(growth_low_benchmark, approval_low_benchmark, :growth)
@approval_zone = Zone.new(approval_low_benchmark, ideal_low_benchmark, :approval)
@ideal_zone = Zone.new(ideal_low_benchmark, 5, :ideal)
end
def zone_for_score(score)
case score
when ideal_zone.low_benchmark..ideal_zone.high_benchmark
ideal_zone
when approval_zone.low_benchmark..approval_zone.high_benchmark
approval_zone
when growth_zone.low_benchmark..growth_zone.high_benchmark
growth_zone
when watch_zone.low_benchmark..watch_zone.high_benchmark
watch_zone
else
warning_zone
end
end
end

@ -0,0 +1,36 @@
module ConstructGraphParameters
TOTAL_GRAPH_WIDTH = 1152
GRAPH_WIDTH = 0.75 * TOTAL_GRAPH_WIDTH
CONSTRUCT_ROW_HEIGHT = 40
CONSTRUCT_ROW_BAR_HEIGHT = 20
module ZoneColor
WARNING = "#FF73C0"
WATCH = "#F096AD"
GROWTH = "#E0BA9A"
APPROVAL = "#D0DD86"
IDEAL = "#C0FF73"
end
class ZoneParams
attr_reader :left_edge
attr_reader :width
def initialize(left_edge:, width:)
@left_edge = left_edge
@width = width
end
def right_edge
left_edge + width
end
end
WARNING_ZONE = ZoneParams.new left_edge: 0, width: (GRAPH_WIDTH / 2) / 3
WATCH_ZONE = ZoneParams.new left_edge: WARNING_ZONE.right_edge, width: (GRAPH_WIDTH / 2) / 3
GROWTH_ZONE = ZoneParams.new left_edge: WATCH_ZONE.right_edge, width: (GRAPH_WIDTH / 2) / 3
APPROVAL_ZONE = ZoneParams.new left_edge: GROWTH_ZONE.right_edge, width: (GRAPH_WIDTH / 2) / 2
IDEAL_ZONE = ZoneParams.new left_edge: APPROVAL_ZONE.right_edge, width: (GRAPH_WIDTH / 2) / 2
KEY_BENCHMARK_WIDTH = 2
end

@ -0,0 +1,77 @@
class ConstructGraphRowPresenter
def initialize(construct:, score:)
@construct = construct
@score = score
end
def construct_title
@construct.title
end
def bar_color
case zone.type
when :ideal
ConstructGraphParameters::ZoneColor::IDEAL
when :approval
ConstructGraphParameters::ZoneColor::APPROVAL
when :growth
ConstructGraphParameters::ZoneColor::GROWTH
when :watch
ConstructGraphParameters::ZoneColor::WATCH
else
ConstructGraphParameters::ZoneColor::WARNING
end
end
def bar_width
percentage = (@score - zone.low_benchmark) / (zone.high_benchmark - zone.low_benchmark)
case zone.type
when :ideal
(percentage * ideal_zone_params.width + approval_zone_params.width).round
when :approval
(percentage * approval_zone_params.width).round
when :growth
(percentage * growth_zone_params.width).round
when :watch
(percentage * watch_zone_params.width + growth_zone_params.width).round
else
(percentage * warning_zone_params.width + watch_zone_params.width + growth_zone_params.width).round
end
end
def x_offset
case zone.type
when :ideal, :approval
0
else
bar_width
end
end
private
def zone
@construct.zone_for_score(@score)
end
def ideal_zone_params
ConstructGraphParameters::IDEAL_ZONE
end
def approval_zone_params
ConstructGraphParameters::APPROVAL_ZONE
end
def growth_zone_params
ConstructGraphParameters::GROWTH_ZONE
end
def watch_zone_params
ConstructGraphParameters::WATCH_ZONE
end
def warning_zone_params
ConstructGraphParameters::WARNING_ZONE
end
end

@ -1 +1,54 @@
<h1><%= @school.name %></h1>
<h1><%= @school.name %></h1>
<% heading_gutter = 30 %>
<% graph_height = @construct_graph_row_presenters.length * ConstructGraphParameters::CONSTRUCT_ROW_HEIGHT + heading_gutter %>
<svg viewbox="0 0 <%= ConstructGraphParameters::TOTAL_GRAPH_WIDTH %> <%= graph_height %>" width=<%= ConstructGraphParameters::TOTAL_GRAPH_WIDTH %> height=<%= graph_height %> xmlns="http://www.w3.org/2000/svg">
<% graph_center = ConstructGraphParameters::GRAPH_WIDTH / 2 %>
<% label_padding_right = 24 %>
<% warning_zone = ConstructGraphParameters::WARNING_ZONE %>
<% watch_zone = ConstructGraphParameters::WATCH_ZONE %>
<% growth_zone = ConstructGraphParameters::GROWTH_ZONE %>
<% approval_zone = ConstructGraphParameters::APPROVAL_ZONE %>
<% ideal_zone = ConstructGraphParameters::IDEAL_ZONE %>
<% key_benchmark_width = ConstructGraphParameters::KEY_BENCHMARK_WIDTH %>
<% key_benchmark_left_edge = graph_center - key_benchmark_width / 2 %>
<% construct_row_height = ConstructGraphParameters::CONSTRUCT_ROW_HEIGHT %>
<% construct_row_bar_height = ConstructGraphParameters::CONSTRUCT_ROW_BAR_HEIGHT %>
<svg id="graph-background" x="25%" y="0" width="75%">
<g id="scale-headings">
<text x=<%= warning_zone.left_edge + warning_zone.width / 2 %> y=<%= heading_gutter / 2 %> text-anchor="middle" dominant-baseline="middle">Warning</text>
<text x=<%= watch_zone.left_edge + watch_zone.width / 2 %> y=<%= heading_gutter / 2 %> text-anchor="middle" dominant-baseline="middle">Watch</text>
<text x=<%= growth_zone.left_edge + growth_zone.width / 2 %> y=<%= heading_gutter / 2 %> text-anchor="middle" dominant-baseline="middle">Growth</text>
<text x=<%= approval_zone.left_edge + approval_zone.width / 2 %> y=<%= heading_gutter / 2 %> text-anchor="middle" dominant-baseline="middle">Approval</text>
<text x=<%= ideal_zone.left_edge + ideal_zone.width / 2 %> y=<%= heading_gutter / 2 %> text-anchor="middle" dominant-baseline="middle">Ideal</text>
</g>
<g id="scale-background" transform="translate(0, <%= heading_gutter %>)">
<rect id="warning-zone" x=<%= warning_zone.left_edge %> y="0" width=<%= warning_zone.width %> height="100%" fill=<%= ConstructGraphParameters::ZoneColor::WARNING %> fill-opacity="0.2" />
<rect id="watch-zone" x=<%= watch_zone.left_edge %> y="0" width=<%= watch_zone.width %> height="100%" fill=<%= ConstructGraphParameters::ZoneColor::WATCH %> fill-opacity="0.2" />
<rect id="growth-zone" x=<%= growth_zone.left_edge %> y="0" width=<%= growth_zone.width %> height="100%" fill=<%= ConstructGraphParameters::ZoneColor::GROWTH %> fill-opacity="0.2" />
<rect id="approval-zone" x=<%= approval_zone.left_edge %> y="0" width=<%= approval_zone.width %> height="100%" fill=<%= ConstructGraphParameters::ZoneColor::APPROVAL %> fill-opacity="0.2" />
<rect id="ideal-zone" x=<%= ideal_zone.left_edge %> y="0" width=<%= ideal_zone.width %> height="100%" fill=<%= ConstructGraphParameters::ZoneColor::IDEAL %> fill-opacity="0.2" />
<rect id="key-benchmark" x=<%= key_benchmark_left_edge %> y="0" width=<%= key_benchmark_width %> height="100%" fill="black" />
</g>
</svg>
<g id="construct-rows">
<svg id="construct-row-labels" x="0" y=<%= heading_gutter %>>
<%= @construct_graph_row_presenters.each_with_index do |presenter, index| %>
<text x="25%" dx=<%= -1 * label_padding_right %> y=<%= index * construct_row_height + construct_row_height / 2 %> text-anchor="end" dominant-baseline="middle"><%= presenter.construct_title %></text>
<% end %>
</svg>
<svg id="construct-row-bars" x="25%" y=<%= heading_gutter %>>
<%= @construct_graph_row_presenters.each_with_index do |presenter, index| %>
<rect x=<%= graph_center - presenter.x_offset %> y=<%= index * construct_row_height + (construct_row_height - construct_row_bar_height) / 2 %> width="<%= presenter.bar_width %>" height=<%= construct_row_bar_height %> fill=<%= presenter.bar_color %> />
<% end %>
</svg>
</g>
</svg>

@ -0,0 +1,119 @@
require 'rails_helper'
RSpec.describe "construct graph row presenter" do
let(:watch_low_benchmark) { 2.9 }
let(:growth_low_benchmark) { 3.1 }
let(:approval_low_benchmark) { 3.6 }
let(:ideal_low_benchmark) { 3.8 }
let(:construct) {
Construct.new(
title: 'Some Title',
watch_low_benchmark: watch_low_benchmark,
growth_low_benchmark: growth_low_benchmark,
approval_low_benchmark: approval_low_benchmark,
ideal_low_benchmark: ideal_low_benchmark
)
}
let(:presenter) {
ConstructGraphRowPresenter.new construct: construct, score: score
}
shared_examples_for 'construct_title' do
it('returns the construct title') do
expect(presenter.construct_title).to eq 'Some Title'
end
end
context('when the score is in the Ideal zone') do
let(:score) { 4.4 }
it_behaves_like 'construct_title'
it('returns the correct color') do
expect(presenter.bar_color).to eq ConstructGraphParameters::ZoneColor::IDEAL
end
it('returns a bar width equal to the approval zone width plus the proportionate ideal zone width') do
expect(presenter.bar_width).to eq 324
end
it('returns an x-offset of 0') do
expect(presenter.x_offset).to eq 0
end
end
context('when the score is in the Approval zone') do
let(:score) { 3.7 }
it_behaves_like 'construct_title'
it("returns the correct color") do
expect(presenter.bar_color).to eq ConstructGraphParameters::ZoneColor::APPROVAL
end
it('returns a bar width equal to the proportionate approval zone width') do
expect(presenter.bar_width).to eq 108
end
it('returns an x-offset of 0') do
expect(presenter.x_offset).to eq 0
end
end
context('when the score is in the Growth zone') do
let(:score) { 3.2 }
it_behaves_like 'construct_title'
it("returns the correct color") do
expect(presenter.bar_color).to eq ConstructGraphParameters::ZoneColor::GROWTH
end
it('returns a bar width equal to the proportionate growth zone width') do
expect(presenter.bar_width).to eq 29
end
it('returns an x-offset equal to the bar width') do
expect(presenter.x_offset).to eq 29
end
end
context('when the score is in the Watch zone') do
let(:score) { 3.0 }
it_behaves_like 'construct_title'
it("returns the correct color") do
expect(presenter.bar_color).to eq ConstructGraphParameters::ZoneColor::WATCH
end
it('returns a bar width equal to the proportionate watch zone width plus the growth zone width') do
expect(presenter.bar_width).to eq 216
end
it('returns an x-offset equal to the bar width') do
expect(presenter.x_offset).to be > 0
end
end
context('when the score is in the Warning zone') do
let(:score) { 2.8 }
it_behaves_like 'construct_title'
it("returns the correct color") do
expect(presenter.bar_color).to eq ConstructGraphParameters::ZoneColor::WARNING
end
it('returns a bar width equal to the proportionate warning zone width plus the watch & growth zone widths') do
expect(presenter.bar_width).to eq 424
end
it('returns an x-offset equal to the bar width') do
expect(presenter.x_offset).to eq 424
end
end
end
Loading…
Cancel
Save