Election results in the London Borough of Sutton.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

247 lignes
7.9 KiB

  1. require 'data_mapper'
  2. class Poll
  3. include DataMapper::Resource
  4. property :district_id, Integer, :key => true
  5. property :election_id, Integer, :key => true
  6. property :electorate, Integer # The number of people eligible to vote in this district in this election
  7. property :ballot_papers_issued, Integer # The number of ballot papers issued (includes spoiled ballots)
  8. property :seats, Integer, :required => true # The number of seats to be elected in this district in this election
  9. property :rejected_no_official_mark, Integer
  10. property :rejected_too_many_candidates, Integer
  11. property :rejected_identifiable_voter, Integer
  12. property :rejected_blank_or_uncertain, Integer
  13. def turnout_percent
  14. @ballot_papers_issued.to_f / @electorate.to_f * 100.0
  15. end
  16. def total_rejected_ballots
  17. @rejected_no_official_mark + \
  18. @rejected_too_many_candidates + \
  19. @rejected_identifiable_voter + \
  20. @rejected_blank_or_uncertain
  21. end
  22. belongs_to :election
  23. belongs_to :district
  24. end
  25. class PollingStation
  26. include DataMapper::Resource
  27. property :id, String, :key => true, :length => 2 # e.g. "KA"
  28. property :name, String, :length => 255#, :required => true
  29. property :address, String, :length => 255#, :required => true
  30. property :postcode, String#, :required => true
  31. property :easting, Float, :required => true
  32. property :northing, Float, :required => true
  33. property :lat, Float, :required => true
  34. property :lng, Float, :required => true
  35. has n, :postcodes
  36. end
  37. class Postcode
  38. include DataMapper::Resource
  39. # Postcode natural key, uppercase with space, eg. "SM1 1EA"
  40. # Column names derived from Ordnance Survey CodePoint Open
  41. property :postcode, String, :key => true
  42. property :positional_quality_indicator, Integer
  43. property :eastings, Integer, :required => true
  44. property :northings, Integer, :required => true
  45. property :country_code, String, :required => true
  46. property :nhs_regional_ha_code, String, :required => true
  47. property :nhs_ha_code, String, :required => true
  48. property :admin_county_code, String # NULL within Greater London
  49. property :admin_district_code, String, :required => true # e.g. London Borough of Sutton
  50. property :admin_ward_code, String, :required => true # e.g. Sutton Central
  51. property :lat, Float, :required => true
  52. property :lng, Float, :required => true
  53. property :ward_id, Integer, :required => true # Sutton Council
  54. property :constituency_id, Integer, :required => false # UK Parliament
  55. property :polling_station_id, String, :length => 2
  56. belongs_to :district, :child_key => [:ward_id]
  57. belongs_to :polling_station
  58. def self.finder(postcode)
  59. postcode = postcode.strip.upcase
  60. if o = self.get(postcode)
  61. return o
  62. end
  63. result = Pat.get(postcode)
  64. unless result.code == 404
  65. # cache API result
  66. self.create(
  67. :postcode => postcode,
  68. :lat => result['geo']['lat'],
  69. :lng => result['geo']['lng'],
  70. :district_name => result['administrative']['district']['title'],
  71. :district_code => result['administrative']['district']['uri'].match(/.+\/(.+)$/)[1],
  72. :ward_name => result['administrative']['ward']['title'],
  73. :ward_code => result['administrative']['ward']['uri'].match(/.+\/(.+)$/)[1]
  74. )
  75. else
  76. # invalid postcode
  77. nil
  78. end
  79. end
  80. end
  81. class Candidate
  82. include DataMapper::Resource
  83. property :id, Serial
  84. property :forenames, String, :required => true
  85. property :surname, String, :required => true, :index => true
  86. has n, :candidacies
  87. def short_name
  88. @forenames.split(' ')[0] + ' ' + @surname
  89. end
  90. def name
  91. @forenames + ' ' + @surname
  92. end
  93. end
  94. class DeletedCandidate
  95. include DataMapper::Resource
  96. property :old_candidate_id, Integer, :key => true # ID of candidate that has been merged/deleted
  97. property :candidate_id, Integer, :required => true # ID of candidate that has been kept
  98. end
  99. class Candidacy
  100. include DataMapper::Resource
  101. property :id, Serial
  102. property :election_id, Integer, :required => true
  103. property :candidate_id, Integer, :required => true
  104. property :party_id, Integer
  105. property :district_id, Integer, :required => true
  106. property :votes, Integer
  107. property :address, String, :length => 200
  108. property :postcode, String
  109. property :position, Integer # Position of this candidate in this district. (1..n)
  110. property :seats, Integer # Number of seats won by this candidacy (0 or 1)
  111. property :labcoop, Boolean, :default => false # Candidacy is for joint Labour/Co-op party
  112. belongs_to :election
  113. belongs_to :candidate
  114. belongs_to :party
  115. belongs_to :district
  116. end
  117. class Campaign
  118. include DataMapper::Resource
  119. property :party_id, Integer, :key => true
  120. property :election_id, Integer, :key => true
  121. property :party_url, String, :length => 255
  122. property :manifesto_html_url, String, :length => 255
  123. property :manifesto_pdf_url, String, :length => 255
  124. belongs_to :party
  125. belongs_to :election
  126. end
  127. class Election
  128. include DataMapper::Resource
  129. property :id, Serial
  130. property :body_id, Integer, :required => true
  131. property :d, Date, :required => true, :index => true
  132. property :reason, String, :length => 255
  133. property :kind, String, :length => 255
  134. has n, :candidacies
  135. has n, :polls
  136. belongs_to :body
  137. has n, :campaigns
  138. def self.past
  139. self.all(:d.lt => Time.now.to_s, :order => [ :d.desc ])
  140. end
  141. def self.future
  142. self.all(:d.gte => Time.now.to_s, :order => [ :d.desc ])
  143. end
  144. # electorate and ballot_papers_issued assume there's a Poll object for every district in this election
  145. def electorate
  146. Poll.sum(:electorate, :election => self)
  147. end
  148. def ballot_papers_issued
  149. Poll.sum(:ballot_papers_issued, :election => self)
  150. end
  151. end
  152. class District
  153. include DataMapper::Resource
  154. property :id, Serial
  155. property :body_id, Integer, :required => true
  156. property :name, String, :length => 255, :required => true
  157. property :slug, String
  158. property :seats, Integer
  159. property :ons_district_code, String
  160. belongs_to :body
  161. has n, :postcodes, :child_key => [:ward_id]
  162. has n, :polls
  163. def self.slugify(name)
  164. name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  165. end
  166. end
  167. class Body
  168. include DataMapper::Resource
  169. property :id, Serial
  170. property :name, String, :length => 255, :required => true
  171. property :district_name, String, :length => 255, :required => true # singular
  172. property :districts_name, String, :length => 255, :required => true # plural
  173. property :slug, String, :length => 255
  174. has n, :elections
  175. has n, :districts
  176. end
  177. class Party
  178. include DataMapper::Resource
  179. property :id, Serial
  180. property :name, String, :required => true
  181. property :colour, String
  182. has n, :candidacies
  183. has n, :campaigns
  184. end
  185. class Ward
  186. include DataMapper::Resource
  187. property :id, Serial
  188. property :slug, String, :required => true
  189. property :ons_id, String, :required => true
  190. property :name, String, :required => true
  191. def self.slugify(name)
  192. name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  193. end
  194. end
  195. DataMapper.setup(:default, ENV['DATABASE_URL'] || "postgres://postgres@localhost:5432/suttonelections")
  196. DataMapper.auto_upgrade!