Module: ActsAsMeritocracy::InstanceMethods

Defined in:
lib/acts_as_meritocracy/model.rb

Instance Method Summary collapse

Instance Method Details

#best_decision(tie_method = "random") ⇒ Object

majority vote (get the decision with the higher number of votes)



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/acts_as_meritocracy/model.rb', line 65

def best_decision(tie_method="random")
  best=nil
  tie=[]
  nb_categories=0
  self.vote_distribution.each { |category|
    if ((best.nil?) || (category.freq>best.freq))
      best=category
      tie=[]
      tie<<category
      # managing tie
    elsif (category.freq==best.freq)
      tie<<category
    end
    nb_categories=nb_categories+1
  }

  # tie detected
  if (tie.size>1)
    case (tie_method)
      when "random" then
        tie[rand(tie.size)].vote
      when "nodecision" then
        nil
    end
    # no vote
  elsif (best.nil?)
    nil
    # get the most chosen category
  else
    best.vote
  end
end

#consensus(method = "kappa") ⇒ Object

Consensus score using the vote distribubtion very high consensus=1 , very low consensus=0 could be used as an indicator to measure the difficulty of users to take collectively a decision 2 methods are proposed

  • Entropy

  • Fleiss Kappa taking into account the weight (NOTE: I removed the pb of chance in the computation)



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/acts_as_meritocracy/model.rb', line 104

def consensus(method="kappa")
  consensus= case method
               when "entropy" then
                 dist=self.vote_distribution
                 nb_votes=dist.inject(0) { |sum, category| sum+category.freq }.to_f
                 h=self.vote_distribution.inject(0) { |h, category|
                   p_j=category.freq.to_f/nb_votes
                   h + p_j*Math.log(p_j)
                 }
                 h=[h, -1].max
                 1+h

               when "kappa" then
                 dist=self.vote_distribution
                 nb_votes=dist.inject(0) { |sum, category| sum+category.freq }.to_f
                 fact=dist.inject(0) { |fact, category|
                   fact+category.freq**2
                 }
                 (fact-nb_votes)/(nb_votes*(nb_votes-1))
               else
                 0
             end
  consensus
end

#nb_votes(weighted = true) ⇒ Object

number of votes taking into account (or not) the weight of the vote 1 vote with vote_weight=2 ==> 2 votes



51
52
53
54
55
56
57
# File 'lib/acts_as_meritocracy/model.rb', line 51

def nb_votes(weighted=true)
  if (weighted)
    self.votes.sum('vote_weight')
  else
    self.votes.count
  end
end

#submit_vote(user, vote, vote_weight = 1) ⇒ Object

submit or update the vote of someone



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/acts_as_meritocracy/model.rb', line 130

def submit_vote(user, vote, vote_weight=1)

  #check existence
  v=Vote.where(:voter_id=>user.id, :voteable_id=>self.id, :voteable_type => self.class.name).first

  #if not create new vote
  if (v.nil?)
    v=Vote.create(:voter=>user,
                  :voteable=>self,
                  :vote=>vote,
                  :vote_weight=>vote_weight)
    #modify existing vote
  else
    v.update_attributes(:vote=>vote, :vote_weight=>vote_weight)
  end
  v
end

#vote_distributionObject

retrieve the vote distribution



60
61
62
# File 'lib/acts_as_meritocracy/model.rb', line 60

def vote_distribution
  Vote.select("vote, sum(vote_weight) as freq").where(:voteable_id=>self.id).group(:vote).order("freq DESC")
end

#voted_by?(user) ⇒ Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/acts_as_meritocracy/model.rb', line 45

def voted_by?(user)
  self.votes.exists?(:voter_id=>user.id)
end