class Vote::Schulze::Basic

Attributes

candidate_count[R]
candidate_names[R]
play_matrix[R]
ranking[R]
ranking_abc[R]
result_matrix[R]
votes[R]
voting_count[R]
voting_matrix[R]

Public Class Methods

call(voting_data, candidate_count = nil) click to toggle source

All-in-One class method to get a calculated SchulzeBasic object

# File lib/vote/schulze/basic.rb, line 7
def self.call(voting_data, candidate_count = nil)
  new(voting_data, candidate_count).call
end
new(voting_data, candidate_count = nil) click to toggle source
# File lib/vote/schulze/basic.rb, line 15
def initialize(voting_data, candidate_count = nil)
  unless voting_data.is_a?(Vote::Schulze::Input)
    voting_data = Vote::Schulze::Input.new(voting_data, candidate_count)
  end
  @voting_matrix = voting_data.voting_matrix
  @candidate_count = voting_data.candidate_count
  @voting_count = voting_data.voting_count
  @candidate_names = voting_data.candidate_names
  @votes = voting_data.votes
  @play_matrix = ::Matrix.scalar(@candidate_count, 0).extend(Vote::Matrix)
  @result_matrix = ::Matrix.scalar(@candidate_count, 0).extend(Vote::Matrix)
end

Public Instance Methods

call() click to toggle source
# File lib/vote/schulze/basic.rb, line 28
def call
  tap do
    find_matches_with_wins
    find_strongest_paths
    calculate_result
    calculate_ranking
    calculate_ranking_abc
  end
end

Private Instance Methods

calculate_ranking() click to toggle source
# File lib/vote/schulze/basic.rb, line 76
def calculate_ranking
  @ranking = @result_matrix.row_vectors.map(&:sum)
end
calculate_ranking_abc() click to toggle source
# File lib/vote/schulze/basic.rb, line 80
def calculate_ranking_abc
  @ranking_abc =
    @ranking
    .map.with_index { |e, i| [e, @candidate_names[i]] }
    .sort
    .reverse
    .map do |(idx, name)|
      "#{name.length == 1 ? name.upcase : name}:#{@ranking.max - idx + 1}"
    end
end
calculate_result() click to toggle source
# File lib/vote/schulze/basic.rb, line 68
def calculate_result
  @result_matrix.each_with_index do |e, x, y|
    next if x == y

    @result_matrix[x, y] = e + 1 if @play_matrix[x, y] > @play_matrix[y, x]
  end
end
find_matches_with_wins() click to toggle source
# File lib/vote/schulze/basic.rb, line 40
def find_matches_with_wins
  @candidate_count.times do |i|
    @candidate_count.times do |j|
      next if i == j

      @play_matrix[i, j] = @voting_matrix[i, j] if @voting_matrix[i, j] > @voting_matrix[j, i]
    end
  end
end
find_strongest_paths() click to toggle source
# File lib/vote/schulze/basic.rb, line 50
def find_strongest_paths # rubocop:disable Metrics/MethodLength
  @candidate_count.times do |i|
    @candidate_count.times do |j|
      next if i == j

      @candidate_count.times do |k|
        next if i == k
        next if j == k

        @play_matrix[j, k] = [
          @play_matrix[j, k],
          [@play_matrix[j, i], @play_matrix[i, k]].min
        ].max
      end
    end
  end
end