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 def votes_per_interval
26 @election = Election.find(params[:id])
27 data, labels = get_votes_per_interval_data(@election)
29 line = Gruff::Line.new("700x400")
30 line.theme = { :background_colors => ['#73BF26', '#ffffff'] }
31 line.title = "Voters Over Time"
32 line.font = File.expand_path('/usr/X11R6/lib/X11/fonts/TTF/Vera.ttf',
35 line.data("#{@election.name}", data )
38 line.x_axis_label = "Intervals"
39 line.y_axis_label = "Number of Votes"
40 line.minimum_value = 0.0
43 send_data(line.to_blob, :disposition => 'inline', :type => 'image/png')
48 # generate the data and labels for each graph
49 def get_votes_per_day_data(election)
50 voter_days = Array.new
51 unique_days = Array.new
52 total_per_day = Array.new
53 election_days = Hash.new
55 #turn election startdate into date object, and create the range of election
56 startdate = Date.parse(election.startdate.to_s)
57 election_range = startdate..Date.today
59 # create a hash with all the dates of the election in String format
60 # referenced by their order in the election
61 election_range.each_with_index do |day, index|
62 election_days[index] = day.to_s
65 # Now I need to create an array with all the times votes were made
66 election.votes.each do |vote|
67 voter_days << Date.parse(vote.time.to_s)
71 # Now I need to count how many times each each date appears in voter_days,
72 # and put that number into a votes_per_day array, the 'data' for the graph
73 #Create an array of unique days from voter_days
74 voter_days.each do |day|
75 unless unique_days.any? {|date| date.eql?(day)}
81 #find all dates where those days = date at current index, put size of returned
82 #array into total_per_day
83 unique_days.each_with_index do |date, index|
84 total_per_day << (voter_days.select {|day| day.eql?(date)}).size
87 # return the data and the labels
88 return total_per_day, election_days
92 def get_votes_per_interval_data(election)
93 labels_hash = Hash.new
95 total_per_interval = Array.new
97 starttime = election.startdate
98 timedelta = Time.now - starttime
100 interval_length = timedelta/numcols
102 # Make a hash, buckets, indexed by time intervals and containing empty arrays
103 # The time object must come first in addition!
104 # i would start at 0, i+1 goes from 0 up till numcols
105 numcols.times {|i| buckets[starttime + ((i+1)*interval_length)] = []}
107 # Put votes into bucket according to the time interval to which they belong,
108 # referenced by their key
109 # Will build a graph over time, as each successive interval wil lhave more
111 election.votes.each do |vote|
112 buckets.keys.sort.each do |inter|
114 buckets[inter] << vote
119 total_per_interval = buckets.keys.sort.collect {|key| buckets[key].size}
121 # Create the hash for the labels. Each graph has ten columns, and three
123 if timedelta < 2.hours #under two hours use minutes for labels
124 labels_hash[0] = starttime.min.to_s
125 labels_hash[(numcols/2)-1] = (starttime + (timedelta/2)).min.to_s
126 labels_hash[numcols-1] = Time.now.min.to_s
127 elsif timedelta < 2.days #more than 2 hours means use hours for labels
128 labels_hash[0] = starttime.hour.to_s
129 labels_hash[(numcols/2)-1] = (starttime + (timedelta/2)).hour.to_s
130 labels_hash[numcols-1] = Time.now.hour.to_s
131 else #more than 2 days means use dates for labels
132 labels_hash[0] = (Date.parse(starttime.to_s)).to_s
133 labels_hash[(numcols/2)-1] = (Date.parse(starttime + (timedelta/2))).to_s
134 labels_hash[numcols-1] = (Date.today).to_s
137 # Make sure to return an array for data and hash for labels
138 return total_per_interval, labels_hash