Election results in the London Borough of Sutton.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

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