Election results in the London Borough of Sutton.
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.
 
 
 
 

210 lines
5.5 KiB

  1. #!/usr/bin/env ruby
  2. require 'petrify'
  3. require_relative '../models'
  4. require_relative '../lib/helpers'
  5. def gen_info_pages
  6. Petrify.page('about', 'about')
  7. Petrify.page('guides', 'guides')
  8. Petrify.page(%w(guides how-the-parliament-election-works), 'parliament')
  9. Petrify.page(%w(guides how-the-council-election-works), 'election')
  10. end
  11. def gen_bodies_pages
  12. # Body detail pages
  13. Body.each do |b|
  14. locals = {
  15. body: b,
  16. districts: District.all(:body => b, :order => [:name])
  17. }
  18. locals['elections'] = repository(:default).adapter.select("
  19. SELECT
  20. e.id,
  21. e.kind,
  22. e.d,
  23. SUM(p.ballot_papers_issued)::float / SUM(p.electorate) * 100 AS turnout_percent
  24. FROM elections e
  25. LEFT JOIN polls p
  26. ON e.id = p.election_id
  27. WHERE e.body_id = ?
  28. GROUP BY p.election_id, e.id
  29. ORDER BY e.d DESC
  30. ", b.id)
  31. Petrify.page(['bodies', b.slug], 'body', locals)
  32. # Districts for this body
  33. b.districts.each do |d|
  34. locals = {
  35. district: d,
  36. body: b
  37. }
  38. Petrify.page(['bodies', b.slug, b.districts_name, d.slug], 'district', locals)
  39. end
  40. end
  41. end
  42. def gen_candidates_pages
  43. # Candidate index
  44. locals = { candidates: Candidate.all(:order => [ :surname, :forenames ]) }
  45. Petrify.page('candidates', 'candidates', locals)
  46. # Candidate pages
  47. # FIXME: What do we do about deleted candidates/redirects?
  48. Candidate.each do |c|
  49. locals = {
  50. candidate: c
  51. }
  52. locals['candidacies'] = repository(:default).adapter.select("
  53. SELECT
  54. e.d,
  55. c.*,
  56. p.name AS party_name,
  57. p.colour AS party_colour,
  58. b.name AS body_name,
  59. b.slug AS body_slug,
  60. b.districts_name AS districts_name,
  61. d.name AS district_name,
  62. d.slug AS district_slug
  63. FROM candidacies c
  64. INNER JOIN elections e
  65. ON c.election_id = e.id
  66. INNER JOIN parties p
  67. ON c.party_id = p.id
  68. INNER JOIN bodies b
  69. ON e.body_id = b.id
  70. INNER JOIN districts d
  71. ON c.district_id = d.id
  72. WHERE c.candidate_id = ?
  73. ORDER BY d
  74. ", c.id)
  75. Petrify.page(['candidates', c.id.to_s], 'candidate', locals)
  76. end
  77. end
  78. def gen_elections_pages
  79. # Election pages
  80. Election.each do |e|
  81. locals = {
  82. body: Body.first(:slug => e.body.slug),
  83. election: Election.first(:body => e.body, :d => e.d),
  84. elections_for_this_body: Election.all(:body => e.body, :order => [:d]),
  85. total_seats: Candidacy.sum(:seats, :election => e),
  86. total_votes: Candidacy.sum(:votes, :election => e)
  87. }
  88. # There's got to be a better way to do this, either with SQL or Datamapper
  89. locals['total_districts'] = repository(:default).adapter.select("
  90. SELECT district_id
  91. FROM candidacies
  92. WHERE election_id = ?
  93. GROUP BY district_id
  94. ORDER BY district_id
  95. ", e.id).count
  96. locals['results_by_party'] = repository(:default).adapter.select("
  97. SELECT
  98. p.colour,
  99. p.name,
  100. SUM(c.votes) AS votez,
  101. SUM(c.seats) AS seatz,
  102. COUNT(*) AS cands
  103. FROM candidacies c
  104. LEFT JOIN parties p ON p.id = c.party_id
  105. WHERE c.election_id = ?
  106. GROUP BY c.party_id, p.colour, p.name
  107. ORDER BY seatz DESC, votez DESC
  108. ", e.id)
  109. Petrify.page(['bodies', e.body.slug, 'elections', e.d.to_s], 'electionsummary', locals)
  110. # District results for this election (resultsdistrict)
  111. # Loop through all districts in this election
  112. e.candidacies.districts.each do |d|
  113. total_seats = Candidacy.sum(:seats, :district => d, :election => e)
  114. total_votes = Candidacy.sum(:votes, :district => d, :election => e)
  115. poll = Poll.get(d.id, e.id)
  116. locals = {
  117. district: d,
  118. body: d.body,
  119. election: e,
  120. candidacies: Candidacy.all(:district => d, :election => e, :order => [:position]),
  121. total_votes: total_votes,
  122. total_candidates: Candidacy.count(:district => d, :election => e),
  123. total_seats: total_seats,
  124. districts_in_this_election: e.candidacies.districts,
  125. poll: poll
  126. }
  127. locals['share_message'] = nil
  128. if total_seats == 1
  129. locals['share_denominator'] = total_votes
  130. elsif poll && poll.valid_ballot_papers
  131. locals['share_denominator'] = poll.valid_ballot_papers
  132. else
  133. locals['share_denominator'] = total_votes / total_seats
  134. locals['share_message'] = "The vote share percentages have been estimated as we don't have data for the number of valid ballot papers in this poll."
  135. end
  136. # Postgres: All the columns selected when using GROUP BY must either be aggregate functions or appear in the GROUP BY clause
  137. locals['results_by_party'] = repository(:default).adapter.select("
  138. SELECT
  139. p.name AS party_name,
  140. p.colour AS party_colour,
  141. COUNT(c.id) AS num_candidates,
  142. SUM(c.seats) AS num_seats,
  143. SUM(c.votes) AS total_votes
  144. FROM candidacies c
  145. LEFT JOIN parties p
  146. ON c.party_id = p.id
  147. WHERE c.district_id = ?
  148. AND c.election_id = ?
  149. GROUP BY p.name, p.colour
  150. ORDER BY total_votes DESC
  151. ", d.id, e.id)
  152. Petrify.page(['bodies', e.body.slug, 'elections', e.d.to_s, e.body.districts_name, d.slug], 'resultsdistrict', locals)
  153. end
  154. end
  155. end
  156. def gen_homepage
  157. locals = {
  158. future_elections: Election.future,
  159. past_elections: Election.past
  160. }
  161. Petrify.page('.', 'index', locals)
  162. end
  163. Petrify.setup
  164. gen_homepage
  165. gen_elections_pages
  166. gen_bodies_pages
  167. gen_info_pages
  168. gen_candidates_pages