2 class GraphController < ApplicationController
3 # produce a graph of votes per day during an election
5 @election = Election.find(params[:id])
6 data, labels = get_votes_per_day_data(@election)
8 line = Gruff::Line.new("700x400")
9 line.theme = { :background_colors => ['#73BF26', '#ffffff'] }
10 line.title = "Voters Per Day"
11 line.font = File.expand_path('/usr/X11R6/lib/X11/fonts/TTF/Vera.ttf',
14 line.data("#{@election.name}", data )
17 line.x_axis_label = "Date"
18 line.y_axis_label = "Number of Votes"
19 line.minimum_value = 0.0
22 send_data(line.to_blob, :disposition => 'inline', :type => 'image/png')
25 #will place votes in a fixed number of intervals, and shows votes over time
26 def votes_per_interval
27 @election = Election.find(params[:id])
28 data, labels = get_votes_per_interval_data(@election)
30 line = Gruff::Line.new("700x400")
31 line.theme = { :background_colors => ['#73BF26', '#ffffff'] }
32 line.title = "Voters Over Time"
33 line.font = File.expand_path('/usr/X11R6/lib/X11/fonts/TTF/Vera.ttf',
36 line.data("#{@election.name}", data )
39 line.x_axis_label = "Intervals"
40 line.y_axis_label = "Number of Votes"
41 line.minimum_value = 0.0
44 send_data(line.to_blob, :disposition => 'inline', :type => 'image/png')
48 @election = Election.find(params[:id])
52 @election = Election.find(params[:id])
54 #Get the list of candidates from the election, and calculate how RubyVote
56 @election.candidates.each do |candidate|
58 #Tabulate how many points each candidate received
59 #Make the name of each candidate a label under the correspoding column
66 # generate the data and labels for each graph
67 def get_votes_per_day_data(election)
68 voter_days = Array.new
69 unique_days = Array.new
70 total_per_day = Array.new
71 election_days = Hash.new
73 #turn election startdate into date object, and create the range of election
74 startdate = Date.parse(election.startdate.to_s)
75 election_range = startdate..Date.today
77 # create a hash with all the dates of the election in String format
78 # referenced by their order in the election
79 election_range.each_with_index do |day, index|
80 election_days[index] = day.to_s
83 # Now I need to create an array with all the times votes were made
84 election.votes.each do |vote|
85 voter_days << Date.parse(vote.time.to_s)
89 # Now I need to count how many times each each date appears in voter_days,
90 # and put that number into a votes_per_day array, the 'data' for the graph
91 #Create an array of unique days from voter_days
92 voter_days.each do |day|
93 unless unique_days.any? {|date| date.eql?(day)}
99 #find all dates where those days = date at current index, put size of returned
100 #array into total_per_day
101 unique_days.each_with_index do |date, index|
102 total_per_day << (voter_days.select {|day| day.eql?(date)}).size
105 # return the data and the labels
106 return total_per_day, election_days
110 def get_votes_per_interval_data(election)
111 labels_hash = Hash.new
113 total_per_interval = Array.new
115 starttime = election.startdate
116 timedelta = Time.now - starttime
118 interval_length = timedelta/numcols
120 # Make a hash, buckets, indexed by time intervals and containing empty arrays
121 # The time object must come first in addition!
122 # i would start at 0, i+1 goes from 0 up till numcols
123 numcols.times {|i| buckets[starttime + ((i+1)*interval_length)] = []}
125 # Put votes into bucket according to the time interval to which they belong,
126 # referenced by their key
127 # Will build a graph over time, as each successive interval wil lhave more
129 election.votes.each do |vote|
130 buckets.keys.sort.each do |inter|
132 buckets[inter] << vote
137 total_per_interval = buckets.keys.sort.collect {|key| buckets[key].size}
139 # Create the hash for the labels. Each graph has ten columns, and three
141 if timedelta < 2.hours #under two hours use minutes for labels
142 labels_hash[0] = starttime.min.to_s
143 labels_hash[(numcols/2)-1] = (starttime + (timedelta/2)).min.to_s
144 labels_hash[numcols-1] = Time.now.min.to_s
145 elsif timedelta < 2.days #more than 2 hours means use hours for labels
146 labels_hash[0] = starttime.hour.to_s
147 labels_hash[(numcols/2)-1] = (starttime + (timedelta/2)).hour.to_s
148 labels_hash[numcols-1] = Time.now.hour.to_s
149 else #more than 2 days means use dates for labels
150 labels_hash[0] = (Date.parse(starttime.to_s)).to_s
151 labels_hash[(numcols/2)-1] = (Date.parse(starttime + (timedelta/2))).to_s
152 labels_hash[numcols-1] = (Date.today).to_s
155 # Make sure to return an array for data and hash for labels
156 return total_per_interval, labels_hash