aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/controllers/public_body_controller.rb125
-rw-r--r--app/models/public_body.rb59
-rw-r--r--app/views/public_body/statistics.html.erb32
-rw-r--r--public/javascripts/stats-graphs.js5
4 files changed, 130 insertions, 91 deletions
diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb
index 244fdfc92..b5d4ede90 100644
--- a/app/controllers/public_body_controller.rb
+++ b/app/controllers/public_body_controller.rb
@@ -156,94 +156,65 @@ class PublicBodyController < ApplicationController
# Make sure minimum_requests is > 0 to avoid division-by-zero
minimum_requests = [minimum_requests, 1].max
total_column = 'info_requests_count'
- graphs =
- [[total_column,
- [{
- :title => 'Public bodies with the most requests',
- :y_axis => 'Number of requests',
- :highest => true}]],
- ['info_requests_successful_count',
- [{
- :title => 'Public bodies with the most successful requests',
- :y_axis => 'Percentage of total requests',
- :highest => true},
- {
- :title => 'Public bodies with the fewest successful requests',
- :y_axis => 'Percentage of total requests',
- :highest => false}]],
- ['info_requests_overdue_count',
- [{
- :title => 'Public bodies with most overdue requests',
- :y_axis => 'Percentage of requests that are overdue',
- :highest => true}]],
- ['info_requests_not_held_count',
- [{
- :title => 'Public bodies that most frequently replied with "Not Held"',
- :y_axis => 'Percentage of total requests',
- :highest => true}]]]
@graph_list = []
- graphs.each do |column, graphs_properties|
- graphs_properties.each do |graph_properties|
- ordering = "y_value"
- reverse = false
- percentages = (column != total_column)
- if graph_properties[:highest]
- ordering = "y_value DESC"
- reverse = true
- end
- y_value_column = total_column
- if percentages
- y_value_column = "(cast(#{column} as float) / #{total_column})"
- end
- where_clause = "#{total_column} >= #{minimum_requests}"
- public_bodies = PublicBody.select("*, #{y_value_column} AS y_value").order(ordering).where(where_clause).limit(per_graph)
- public_bodies.reverse! if reverse
+ [[total_column,
+ [{
+ :title => 'Public bodies with the most requests',
+ :y_axis => 'Number of requests',
+ :highest => true}]],
+ ['info_requests_successful_count',
+ [{
+ :title => 'Public bodies with the most successful requests',
+ :y_axis => 'Percentage of total requests',
+ :highest => true},
+ {
+ :title => 'Public bodies with the fewest successful requests',
+ :y_axis => 'Percentage of total requests',
+ :highest => false}]],
+ ['info_requests_overdue_count',
+ [{
+ :title => 'Public bodies with most overdue requests',
+ :y_axis => 'Percentage of requests that are overdue',
+ :highest => true}]],
+ ['info_requests_not_held_count',
+ [{
+ :title => 'Public bodies that most frequently replied with "Not Held"',
+ :y_axis => 'Percentage of total requests',
+ :highest => true}]]].each do |column, graphs_properties|
- x_values = public_bodies.each_with_index.map { |public_body, index| index }
- y_values = public_bodies.map { |pb| pb.y_value.to_f }
- cis_below = nil
- cis_above = nil
+ graphs_properties.each do |graph_properties|
- if percentages
- original_values = public_bodies.map { |pb| pb.send(column) }
- original_totals = public_bodies.map { |pb| pb.send(total_column) }
- # Calculate confidence intervals:
- cis_below = []
- cis_above = []
- original_totals.each_with_index.map { |total, i|
- lower_ci, higher_ci = ci_bounds original_values[i], total, 0.05
- cis_below.push(y_values[i] - lower_ci)
- cis_above.push(higher_ci - y_values[i])
- }
- # Turn the y values and confidence interval into
- # percentages:
- [y_values, cis_below, cis_above].each { |l|
- l.map! { |v| 100 * v }
- }
- end
+ percentages = (column != total_column)
+ highest = graph_properties[:highest]
- y_max = y_values.max
+ data = nil
if percentages
- y_max = 100
+ data = PublicBody.get_request_percentages(column,
+ per_graph,
+ highest,
+ minimum_requests)
+ else
+ data = PublicBody.get_request_totals(per_graph,
+ highest,
+ minimum_requests)
end
- graph_id = "#{column}-"
- graph_id += graph_properties[:highest] ? 'highest' : 'lowest'
-
- @graph_list.push({
- 'id' => graph_id,
- 'errorbars' => percentages,
- 'title' => graph_properties[:title],
- 'x_values' => x_values,
- 'y_values' => y_values,
- 'cis_below' => cis_below,
- 'cis_above' => cis_above,
+ data_to_draw = {
+ 'id' => "#{column}-#{highest ? 'highest' : 'lowest'}",
'x_axis' => 'Public Bodies',
- 'x_ticks' => public_bodies.each_with_index.map { |pb, i| [i, pb.name] },
'y_axis' => graph_properties[:y_axis],
- 'y_max' => y_max})
+ 'errorbars' => percentages,
+ 'title' => graph_properties[:title]}
+
+ if data
+ data_to_draw.update(data)
+ data_to_draw['x_values'] = data['public_bodies'].each_with_index.map { |pb, i| i }
+ data_to_draw['x_ticks'] = data['public_bodies'].each_with_index.map { |pb, i| [i, pb.name] }
+ end
+
+ @graph_list.push data_to_draw
end
end
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index a76aeb189..436418fe5 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -632,6 +632,65 @@ class PublicBody < ActiveRecord::Base
end
end
+ # Return data for the 'n' public bodies with the highest (or
+ # lowest) number of requests, but only returning data for those
+ # with at least 'minimum_requests' requests.
+ def self.get_request_totals(n, highest, minimum_requests)
+ ordering = "info_requests_count"
+ ordering += " DESC" if highest
+ where_clause = "info_requests_count >= #{minimum_requests}"
+ public_bodies = PublicBody.order(ordering).where(where_clause).limit(n)
+ public_bodies.reverse! if highest
+ y_values = public_bodies.map { |pb| pb.info_requests_count }
+ return {
+ 'public_bodies' => public_bodies,
+ 'y_values' => y_values,
+ 'y_max' => y_values.max}
+ end
+
+ # Return data for the 'n' public bodies with the highest (or
+ # lowest) score according to the metric of the value in 'column'
+ # divided by the total number of requests, expressed as a
+ # percentage. This only returns data for those public bodies with
+ # at least 'minimum_requests' requests.
+ def self.get_request_percentages(column, n, highest, minimum_requests)
+ total_column = "info_requests_count"
+ ordering = "y_value"
+ ordering += " DESC" if highest
+ y_value_column = "(cast(#{column} as float) / #{total_column})"
+ where_clause = "#{total_column} >= #{minimum_requests}"
+ public_bodies = PublicBody.select("*, #{y_value_column} AS y_value").order(ordering).where(where_clause).limit(n)
+ public_bodies.reverse! if highest
+ y_values = public_bodies.map { |pb| pb.y_value.to_f }
+
+ original_values = public_bodies.map { |pb| pb.send(column) }
+ # If these are all nil, then probably the values have never
+ # been set; some have to be set by a rake task. In that case,
+ # just return nil:
+ return nil unless original_values.any? { |ov| !ov.nil? }
+
+ original_totals = public_bodies.map { |pb| pb.send(total_column) }
+ # Calculate confidence intervals, as offsets from the proportion:
+ cis_below = []
+ cis_above = []
+ original_totals.each_with_index.map { |total, i|
+ lower_ci, higher_ci = ci_bounds original_values[i], total, 0.05
+ cis_below.push(y_values[i] - lower_ci)
+ cis_above.push(higher_ci - y_values[i])
+ }
+ # Turn the y values and confidence interval offsets into
+ # percentages:
+ [y_values, cis_below, cis_above].each { |l|
+ l.map! { |v| 100 * v }
+ }
+ return {
+ 'public_bodies' => public_bodies,
+ 'y_values' => y_values,
+ 'cis_below' => cis_below,
+ 'cis_above' => cis_above,
+ 'y_max' => 100}
+ end
+
private
def request_email_if_requestable
diff --git a/app/views/public_body/statistics.html.erb b/app/views/public_body/statistics.html.erb
index e370050d2..fc0007d97 100644
--- a/app/views/public_body/statistics.html.erb
+++ b/app/views/public_body/statistics.html.erb
@@ -5,22 +5,26 @@
<% @graph_list.each do |graph_data| %>
<h3 class="public-body-ranking-title"><%= graph_data['title']%></h3>
<div class="public-body-ranking" id="<%= graph_data['id'] %>">
- <table border=0>
- <thead>
- <tr>
- <th>Public Body</th>
- <th><%= graph_data['y_axis'] %></th>
- </tr>
- </thead>
- <tbody>
- <% graph_data['x_ticks'].each_with_index do |pb_and_index, i| %>
+ <% if graph_data['x_values'] %>
+ <table border=0>
+ <thead>
<tr>
- <td><%= pb_and_index[1] %></td>
- <td class="statistic"><%= graph_data['y_values'][i].round %></td>
+ <th>Public Body</th>
+ <th><%= graph_data['y_axis'] %></th>
</tr>
- <% end %>
- </tbody>
- </table>
+ </thead>
+ <tbody>
+ <% graph_data['x_ticks'].each_with_index do |pb_and_index, i| %>
+ <tr>
+ <td><%= pb_and_index[1] %></td>
+ <td class="statistic"><%= graph_data['y_values'][i].round %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ <% else %>
+ <%= _("There was no data calculated for this graph yet.") %>
+ <% end %>
</div>
<% end %>
diff --git a/public/javascripts/stats-graphs.js b/public/javascripts/stats-graphs.js
index 9d9ac5b9d..73e19a6fc 100644
--- a/public/javascripts/stats-graphs.js
+++ b/public/javascripts/stats-graphs.js
@@ -13,6 +13,11 @@ $(document).ready(function() {
graph_data,
graph_div = $('#' + graph_id);
+ if (!graph_data.x_values) {
+ /* Then there's no data for this graph */
+ return true;
+ }
+
graph_div.css('width', '700px');
graph_div.css('height', '400px');