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.
 
 
 
 

211 lines
5.5 KiB

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