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.

models.rb 5.9 KiB

13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
11 years ago
13 years ago
13 years ago
13 years ago
13 years ago
11 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. def successful_candidacies # Candidacies where the candidate was elected
  30. Candidacy.all(:election => @election, :district => @district, :order => [:position], :limit => @seats)
  31. end
  32. # Set candidacy.position for every candidacy in this poll
  33. # Returns array of candidacies, or false if we don't have results for this poll
  34. def set_positions
  35. # Check that every candidacy for this poll has its votes recorded (ie that the election results are known)
  36. return false if Candidacy.count(:conditions => { :district_id => @district_id, :election_id => @election_id, :votes => nil }) > 0
  37. # Get the candidacies for this poll
  38. ccys = Candidacy.all(:conditions => { :district_id => @district_id, :election_id => @election_id }, :order => [:votes.desc])
  39. puts "Found no candidacies for this poll" if ccys.size == 0
  40. position = 1
  41. ccys.each do |ccy|
  42. position <= @seats ? ccy.seats = 1 : ccy.seats = 0
  43. ccy.position = position
  44. ccy.save
  45. position += 1
  46. end
  47. ccys
  48. end
  49. belongs_to :election
  50. belongs_to :district
  51. end
  52. class Candidate
  53. include DataMapper::Resource
  54. property :id, Serial
  55. property :forenames, String, :required => true
  56. property :surname, String, :required => true, :index => true
  57. has n, :candidacies#, 'Candidacy'
  58. def short_name
  59. @forenames.split(' ')[0] + ' ' + @surname
  60. end
  61. def name
  62. @forenames + ' ' + @surname
  63. end
  64. def url
  65. "/candidates/" + @id.to_s
  66. end
  67. end
  68. class DeletedCandidate
  69. include DataMapper::Resource
  70. property :old_candidate_id, Integer, :key => true # ID of candidate that has been merged/deleted
  71. property :candidate_id, Integer, :required => true # ID of candidate that has been kept
  72. end
  73. class Candidacy
  74. include DataMapper::Resource
  75. property :id, Serial
  76. property :election_id, Integer, :required => true
  77. property :candidate_id, Integer, :required => true
  78. property :party_id, Integer
  79. property :district_id, Integer, :required => true
  80. property :votes, Integer
  81. property :address, String, :length => 200
  82. property :postcode, String
  83. property :position, Integer # Position of this candidate in this district. (1..n)
  84. property :seats, Integer # Number of seats won by this candidacy (0 or 1)
  85. property :labcoop, String, :default => '0' # Candidacy is for joint Labour/Co-op party
  86. belongs_to :election
  87. belongs_to :candidate
  88. belongs_to :party
  89. belongs_to :district
  90. end
  91. class Election
  92. include DataMapper::Resource
  93. property :id, Serial
  94. property :body_id, Integer, :required => true
  95. property :d, Date, :required => true, :index => true
  96. property :reason, String, :length => 255
  97. property :kind, String, :length => 255
  98. has n, :candidacies
  99. has n, :polls
  100. belongs_to :body
  101. def self.past
  102. self.all(:d.lt => Time.now.to_s, :order => [ :d.desc ])
  103. end
  104. def self.future
  105. self.all(:d.gte => Time.now.to_s, :order => [ :d.desc ])
  106. end
  107. # electorate and ballot_papers_issued assume there's a Poll object for every district in this election
  108. def electorate
  109. Poll.sum(:electorate, :election => self)
  110. end
  111. def ballot_papers_issued
  112. Poll.sum(:ballot_papers_issued, :election => self)
  113. end
  114. def set_positions
  115. polls.each { |p| p.set_positions }
  116. end
  117. end
  118. class District
  119. include DataMapper::Resource
  120. property :id, Serial
  121. property :body_id, Integer, :required => true
  122. property :name, String, :length => 255, :required => true
  123. property :slug, String
  124. property :ons_district_code, String
  125. belongs_to :body
  126. has n, :polls
  127. def self.slugify(name)
  128. name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  129. end
  130. end
  131. class Body
  132. include DataMapper::Resource
  133. property :id, Serial
  134. property :name, String, :length => 255, :required => true
  135. property :district_name, String, :length => 255, :required => true # singular
  136. property :districts_name, String, :length => 255, :required => true # plural
  137. property :slug, String, :length => 255
  138. has n, :elections
  139. has n, :districts
  140. end
  141. class Party
  142. include DataMapper::Resource
  143. property :id, Serial
  144. property :name, String, :required => true
  145. property :colour, String
  146. has n, :candidacies
  147. # has n, :campaigns
  148. end
  149. DataMapper.setup(:default, ENV['DATABASE_URL'])
  150. DataMapper.repository(:default).adapter.resource_naming_convention = DataMapper::NamingConventions::Resource::UnderscoredAndPluralized
  151. DataMapper.auto_upgrade!