vedia/mj.rb
2026-01-10 19:00:26 -06:00

89 lines
2 KiB
Ruby

class MajorityJudgment
@values = nil
include Comparable
attr_reader :ratings, :count, :n, :majority
class << self
attr_accessor :values
end
def initialize(arg)
if arg.is_a?(Array)
@ratings = arg
@count = { }
self.class.values.each do |v|
@count[v[:id]] = 0
end
@n = 0
ratings.each do |r|
@count.has_key?(r) ? @count[r] = @count[r] + 1 : @count[r] = 1
@n = @n + 1
end
elsif arg.is_a?(Hash)
@count = arg
@n = 0
@count.collect { |r, c| @n = @n + c }
end
@majority = ( @n.to_f / 2 ).floor + 1
end
def mj
s = 0
(1..self.class.values.length).to_a.reverse.each do |r|
s = s + @count[r] if @count[r]
return r if s >= @majority
end
return 0
end
def proponents(rating = self.mj)
p = 0
(rating+1..self.class.values.length).to_a.reverse.each do |r|
p = p + @count[r] if @count[r]
end
return p
end
def opponents(rating = self.mj)
o = 0
(1..rating-1).to_a.reverse.each do |r|
o = o + @count[r] if @count[r]
end
return o
end
def <=> (other)
return 1 if self.mj > other.mj
return -1 if self.mj < other.mj
return 0 if self.mj == 0
counta = self.count.dup
counta[self.mj] = counta[self.mj] - 1
countb = other.count.dup
countb[other.mj] = countb[other.mj] - 1
return MajorityJudgment.new(counta) <=> MajorityJudgment.new(countb)
end
def break_tie(other)
rounds = [ ]
s = MajorityJudgment.new(self.count.dup)
o = MajorityJudgment.new(other.count.dup)
rounds << [s, o]
while s.mj == o.mj and not s.mj == 0
new_s_count = s.count.dup
new_o_count = o.count.dup
new_s_count[s.mj] = new_s_count[s.mj] - 1
new_o_count[o.mj] = new_o_count[o.mj] - 1
s = MajorityJudgment.new(new_s_count)
o = MajorityJudgment.new(new_o_count)
rounds << [s, o]
end
return rounds
end
def to_s
puts "#{@count}: {M=>#{self.mj}, P=>#{self.proponents}, O=>#{self.opponents}}"
end
end