#!/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

