Acts_as_Meritocracy¶ ↑
Mixin enabling a weighted majority voting system for any model with qualitative decisions/categories. As measure of consensus/inter-rater agreement, you can choose between a weighted variant of the Fleiss’s Kappa (by default) or the entropy of the distribution of votes. The consensus score is in the interval [0,1]. very high consensus=1 , very low consensus=0
NOTE: this voting system has been developed to take (collective) a decision about items, not rank items (e.g. by popularity). i.e. generally once a certain level of consensus is reached on a given item, a decision is taken and the vote is close.
scenario¶ ↑
You have a set of items and would like to classify them according to n predefined categories. For that you ask the opinion of the public. Since some people are better/more reliable than others, their votes can be weighted so they have more power in the collective decision.
installation¶ ↑
To use it, add it to your Gemfile:
gem 'acts_as_meritocracy'
Usage¶ ↑
class Item < ActiveRecord::Base
act_as_meritocracy
end
item = Item.create()
#user1 votes for the decision 4, by default the vote_weight=1
item.submit_vote(user1, 4)
# user2 votes for the decision 1 with a vote_weight=2. A vote_weight=2 means that
# the voter has a vote equal to 2 normal voters (vote_weight=1)
item.submit_vote(user2, 1, 2)
# user1 can change/update her vote
item.submit_vote(user1, 1)
# user3 votes for decision 2
item.submit_vote(user3, 2)
# user4 votes for decision 2
item.submit_vote(user4, 3,5)
# getting the most (weighted) voted decision
# tie management: you can manage tie with 2 methods
# - best_decision("random") (by default) returns randomly one of the categories having the same highest frequency
# - best_desion("nodecision") returns nil if a tie is detected
item.best_decision
=>3
# getting the number of votes - with the weight
item.nb_votes(true)
=> 1 + 2 + 1 + 5 = 9
# getting the number of votes - without taking into account the weight
item.nb_votes(false)
=> 1 + 1 + 1 + 1 = 4
# getting the frequency distribution of the decisions [{:decision1=>freq1},{:decision1=>freq2}, ..,].
# the frequency takes into account the vote weight.
item.vote_distribution
=> [ {vote => 1, freq => 3},{vote => 2, freq => 1},{vote => 3,freq => 5} ]
# computing the consensus score based on the vote distribution
# by default I used a variante of the Fleiss Kappa metrics
item.consensus
=> 0.361
# Alternative: computing an entropy-based measure of the consensus
# (A perfect disagreement between 2 categories gives a higher score
# than for 10 categories, less predictable)
item.consensus("entropy")
=>0.063
# retrieving the list of votes {decision, vote_weight).
# so item.votes.where(:vote=>1) retrieves the list of votes having decision=1
item.votes
=> [Vote1<>.,Vote2<>., .., Voten<>. ]
# getting all the items voted by user1
item.voted_by?(user1)
=> yes
# getting all the items voted by user1
Item.voted_by(user1)
=>[item]