#!/usr/bin/ruby19 list = ARGF.argv if list.size != 1 puts "Invalid call. You need to pass the election name to this script" exit(-1) end ElectionName = list.at(0) ResultsFile = "master-" + ElectionName + ".txt" RankingsFile = ElectionName + "-rank.txt" ScaleSize = 14 HeightScale = 5 BarHeight = 8 # Get all candidate names and initialise their vote count candidates = Hash.new ballots = Hash.new File.open ResultsFile, "r" do | file | file.each_line do | line | next if line =~ /^-/ line.split(%r/\s+/).each do | person | candidates[person] = [0] * ScaleSize unless candidates[person] end end file.seek(0, IO::SEEK_SET) key = false file.each_line do | line | if line =~ %r/^-/ key = line.split(/\s+/).grep(/^[a-fA-F0-9]{4}$/)[0] ballots[key] = [] else raise "key not set yet" unless key ballots[key].push line.chomp.split(/\s+/) end end end # Add in missing candidates ballots.keys.each do | key | append_candidates = candidates.keys.dup ballots[key].flatten.each do | candidate | append_candidates.delete_if do | item | item == candidate end end unless append_candidates.empty? ballots[key].push append_candidates end end # Calculate distributions ballots.each_pair do | ballot, results | scale_by = ScaleSize / (0.0 + results.length) results.each_with_index do | result, index | place = (scale_by * index.to_f).to_i raise "out of range" unless (0..ScaleSize - 1).include? place result.each do | candidate | candidates[candidate][place] += 1 end end end # Read in rankings rankings = [] File.open RankingsFile, "r" do | file | file.each_line do | line | key = line.split(/\s+/)[0] rankings << key end end # Display distributions candidates.keys.sort do | a, b | rankings << a unless rankings.index a rankings << b unless rankings.index b (rankings.index a) <=> (rankings.index b) end.each do | candidate | puts " " + candidate + " (" + (rankings.index(candidate) + 1).to_s + ")" BarHeight.downto(0) do | height | print "|" candidates[candidate].each do | value | if value > (height * HeightScale) print "#" else print " " end end puts end puts "+" + ("-" * ScaleSize) puts end