oneclickorgs/one-click-orgs

View on GitHub
app/models/election.rb

Summary

Maintainability
A
0 mins
Test Coverage
class Election < ActiveRecord::Base
  attr_accessible :organisation

  state_machine :initial => :draft do
    event :close do
      transition :open => :closed
    end

    event :start do
      transition :draft => :open
    end

    after_transition :on => :close, :do => :after_close
  end

  belongs_to :organisation
  belongs_to :meeting
  has_many :nominations
  has_many :nominees, :through => :nominations
  has_many :ballots

  validates_presence_of :seats

  def after_close
    run!
  end

  def elected_nominees
    return [] unless closed?
    nominations.elected.map(&:nominee)
  end

  def defeated_nominees
    return [] unless closed?
    nominations.defeated.map(&:nominee)
  end

  def self.close_elections
    # Elections with a voting closing date of today should not be closed until the end
    # of today.
    where(["voting_closing_date < ? AND state = 'open'", Time.now.utc.to_date]).each(&:close!)
  end

  def run!
    me = Meekster::Election.new

    nomination_ids = nominations.map(&:id)

    mc = nomination_ids.map{|id| Meekster::Candidate.new(id.to_s)}

    mb = ballots.map do |b|
      ranking = b.ranking.map{|nomination_id| nomination_ids.index(nomination_id)}
      ranking = ranking.map{|index| mc[index]}
      Meekster::Ballot.new(ranking)
    end

    me.candidates = mc
    me.ballots = mb
    me.seats = seats

    me.run!

    elected = me.candidates.select{|c| c.state == :elected}
    defeated = me.candidates.select{|c| c.state == :defeated}

    elected.each do |c|
      nominations.find(c.name).elect!
    end

    defeated.each do |c|
      nominations.find(c.name).defeat!
    end
  end

  # TODO Remove this; it's for testing purposes only.
  def auto_cast_ballots
    eligible_members = organisation.members - ballots.map(&:member)
    eligible_members.each do |member|
      ballots.create(:ranking => [nominations.first.id], :member => member)
    end
  end
end