Election results in the London Borough of Sutton.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

13 лет назад
14 лет назад
13 лет назад
11 лет назад
11 лет назад
13 лет назад
13 лет назад
13 лет назад
14 лет назад
13 лет назад
14 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
14 лет назад
13 лет назад
13 лет назад
11 лет назад
13 лет назад
11 лет назад
13 лет назад
11 лет назад
13 лет назад
13 лет назад
11 лет назад
13 лет назад
13 лет назад
11 лет назад
13 лет назад
13 лет назад
11 лет назад
13 лет назад
13 лет назад
13 лет назад
14 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
11 лет назад
11 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
12 лет назад
12 лет назад
11 лет назад
12 лет назад
12 лет назад
11 лет назад
12 лет назад
13 лет назад
14 лет назад
13 лет назад
14 лет назад
14 лет назад
13 лет назад
14 лет назад
14 лет назад
13 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. require 'rubygems'
  2. require 'sinatra'
  3. require 'haml'
  4. require './models'
  5. require 'rack-flash'
  6. set :root, File.dirname(__FILE__)
  7. enable :sessions
  8. use Rack::Flash
  9. class String
  10. def pluralize(num)
  11. if num == 1
  12. return self
  13. end
  14. case self[-1]
  15. when 'y'
  16. self[0..-2] + 'ies'
  17. when 's'
  18. self + "es"
  19. else
  20. self + "s"
  21. end
  22. end
  23. end
  24. helpers do
  25. # Format a number with commas for every ^3
  26. def commify(num)
  27. num.to_s.reverse.gsub(/(\d\d\d)(?=\d)(?!\d*\.)/,'\1,').reverse
  28. end
  29. # From http://snippets.dzone.com/posts/show/593
  30. def to_ordinal(num)
  31. num = num.to_i
  32. if (10...20) === num
  33. "#{num}th"
  34. else
  35. g = %w{ th st nd rd th th th th th th }
  36. a = num.to_s
  37. c = a[-1..-1].to_i
  38. a + g[c]
  39. end
  40. end
  41. def format_percent(num)
  42. sprintf("%.0f%%", num)
  43. end
  44. def short_date(d)
  45. d.strftime("%e %b %Y")
  46. end
  47. def long_date(d)
  48. d.strftime("%e %B %Y")
  49. end
  50. # Exception for Labour/Co-operative candidacies
  51. def party_name(labcoop, party_name)
  52. labcoop ? "Labour and Co-operative Party" : party_name
  53. end
  54. end
  55. get '/' do
  56. if params[:postcode]
  57. @postcode = params[:postcode].strip.upcase
  58. if @p = Postcode.get(@postcode)
  59. # Postcode is valid and in LB Sutton
  60. @ward = Ward.get(@p.ward_id)
  61. flash[:notice] = "Postcode <strong>#{@postcode}</strong> is in #{@ward.name} ward"
  62. redirect "/bodies/sutton-council/wards/#{@ward.slug}"
  63. else
  64. flash.now[:error] = "<strong>#{@postcode}</strong> is not a postcode in Sutton"
  65. end
  66. end
  67. # Display a random postcode as default search term
  68. @random_pc = repository(:default).adapter.select("
  69. SELECT postcode
  70. FROM postcodes
  71. ORDER BY RANDOM()
  72. LIMIT 1
  73. ")
  74. @default_pc = @random_pc[0]
  75. @future_elections = Election.future
  76. @past_elections = Election.past
  77. haml :index
  78. end
  79. get '/bodies/:body/elections/:date' do
  80. @body = Body.first(:slug => params[:body])
  81. @election = Election.first(:body => @body, :d => params[:date])
  82. @elections_for_this_body = Election.all(:body => @body, :order => [:d])
  83. @total_seats = Candidacy.sum(:seats, :election => @election)
  84. @total_votes = Candidacy.sum(:votes, :election => @election)
  85. # There's got to be a better way to do this, either with SQL or Datamapper
  86. @total_districts = repository(:default).adapter.select("
  87. SELECT district_id
  88. FROM candidacies
  89. WHERE election_id = ?
  90. GROUP BY district_id
  91. ORDER BY district_id
  92. ", @election.id).count
  93. @results_by_party = repository(:default).adapter.select("
  94. SELECT
  95. p.colour,
  96. p.name,
  97. SUM(c.votes) AS votez,
  98. SUM(c.seats) AS seatz,
  99. COUNT(*) AS cands
  100. FROM candidacies c
  101. LEFT JOIN parties p ON p.id = c.party_id
  102. WHERE c.election_id = ?
  103. GROUP BY c.party_id, p.colour, p.name
  104. ORDER BY seatz DESC, votez DESC
  105. ", @election.id)
  106. @results_by_district = repository(:default).adapter.select("
  107. SELECT
  108. d.name,
  109. d.slug AS district_slug,
  110. SUM(c.seats) AS seats,
  111. SUM(c.votes) AS votez,
  112. COUNT(c.id) AS num_candidates
  113. FROM districts d, candidacies c
  114. WHERE
  115. c.district_id = d.id
  116. AND c.election_id = ?
  117. GROUP BY c.district_id, d.name, d.slug
  118. ORDER BY d.name
  119. ", @election.id)
  120. # For elections that haven't yet been held
  121. @districts_in_this_election = repository(:default).adapter.select("
  122. SELECT DISTINCT d.name, d.slug
  123. FROM candidacies c
  124. LEFT JOIN districts d
  125. ON c.district_id = d.id
  126. WHERE c.election_id = ?
  127. ORDER BY d.name
  128. ", @election.id)
  129. haml :electionsummary
  130. end
  131. # get '/bodies/:body/elections/:date/parties/:party' do
  132. # Not written yet. Show how this party did at this election.
  133. # end
  134. get '/bodies/?' do
  135. @bodies = Body.all
  136. haml :bodies
  137. end
  138. get '/bodies/:body/?' do
  139. @body = Body.first(:slug => params[:body])
  140. @elections = Election.all(:body => @body, :order => [:d.desc])
  141. @districts = District.all(:body => @body, :order => [:name])
  142. haml :body
  143. end
  144. # get '/wards/:slug/postcode/:postcode/?' do
  145. # @ward = Ward.first(:slug => params[:slug])
  146. # @postcode = params[:postcode]
  147. # haml :wards
  148. # end
  149. get '/candidates/:id/?' do
  150. if @deleted_candidate = DeletedCandidate.get(params[:id])
  151. redirect "/candidates/#{@deleted_candidate.candidate_id}", 301 # HTTP 301 Moved Permanently
  152. end
  153. if @candidate = Candidate.get(params[:id])
  154. @candidacies = repository(:default).adapter.select("
  155. SELECT
  156. e.d,
  157. c.*,
  158. p.name AS party_name,
  159. p.colour AS party_colour,
  160. b.name AS body_name,
  161. b.slug AS body_slug,
  162. b.districts_name AS districts_name,
  163. d.name AS district_name,
  164. d.slug AS district_slug
  165. FROM candidacies c
  166. INNER JOIN elections e
  167. ON c.election_id = e.id
  168. INNER JOIN parties p
  169. ON c.party_id = p.id
  170. INNER JOIN bodies b
  171. ON e.body_id = b.id
  172. INNER JOIN districts d
  173. ON c.district_id = d.id
  174. WHERE c.candidate_id = ?
  175. ORDER BY d
  176. ", @candidate.id)
  177. haml :candidate
  178. else
  179. 404
  180. end
  181. end
  182. get '/candidates/?' do
  183. @candidates = Candidate.all(:order => [ :surname, :forenames ])
  184. haml :candidates
  185. end
  186. get '/bodies/:body/elections/:date/:districts_name/:district' do
  187. @district = District.first(:slug => params[:district])
  188. @body = Body.first(:slug => params[:body])
  189. @election = Election.first(:body => @body, :d => params[:date])
  190. @candidacies = Candidacy.all(:district => @district, :election => @election, :order => [:votes.desc])
  191. @total_votes = Candidacy.sum(:votes, :district => @district, :election => @election)
  192. @total_candidates = Candidacy.count(:district => @district, :election => @election)
  193. @total_seats = Candidacy.sum(:seats, :district => @district, :election => @election)
  194. @districts_in_this_election = @election.candidacies.districts
  195. @poll = Poll.get(@district.id, @election.id)
  196. # Postgres: All the columns selected when using GROUP BY must either be aggregate functions or appear in the GROUP BY clause
  197. @results_by_party = repository(:default).adapter.select("
  198. SELECT
  199. p.name AS party_name,
  200. p.colour AS party_colour,
  201. COUNT(c.id) AS num_candidates,
  202. SUM(c.seats) AS num_seats,
  203. SUM(c.votes) AS total_votes
  204. FROM candidacies c
  205. LEFT JOIN parties p
  206. ON c.party_id = p.id
  207. WHERE c.district_id = ?
  208. AND c.election_id = ?
  209. GROUP BY p.name, p.colour
  210. ORDER BY total_votes DESC
  211. ", @district.id, @election.id)
  212. haml :resultsdistrict
  213. end
  214. get '/bodies/:body/:districts_name/:district' do
  215. @district = District.first(:slug => params[:district])
  216. @body = Body.first(:slug => params[:body])
  217. haml :district
  218. end
  219. get '/how-the-council-election-works' do
  220. haml :election
  221. end
  222. get '/how-the-parliament-election-works' do
  223. haml :parliament
  224. end
  225. # get '/voting' do
  226. # haml :voting
  227. # end
  228. get '/error' do
  229. haml :error
  230. end
  231. get '/about' do
  232. haml :about
  233. end
  234. # get '/aliens' do
  235. # haml :aliens
  236. # end
  237. not_found do
  238. haml :not_found
  239. end