class Birdwatcher::Punchcard
Constants
- DAYS
- FONT_FACE
- HOURS
- LEFT_PADDING
- TOP_PADDING
- WIDTH
Public Class Methods
new(timestamps)
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 15 def initialize(timestamps) @timestamps = timestamps end
Public Instance Methods
generate(destination)
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 19 def generate(destination) @data_log = Hash.new { |h, k| h[k] = Hash.new } final_data = [] @timestamps.each do |timestamp| day = timestamp.strftime("%a") hour = timestamp.strftime("%H").to_i @data_log[day][hour] = (@data_log[day][hour] || 0) + 1 end @data_log.each do |d, hour_pair| hour_pair.each do |h, value| glr = @data_log[d][h] * 1.0 glr /= max_value glr *= max_range glrb = get_weight(glr) final_data.push([glrb, get_x_y_from_day_and_hour(d, h)]) end end final_data.each do |x| draw_circle(x[1], x[0]) end surface.write_to_png(destination) end
Private Instance Methods
all_values()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 97 def all_values @all_values = [] @data_log.each do |d, e| e.each do |h, i| @all_values << @data_log[d][h] end end @all_values end
context()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 115 def context @context ||= Cairo::Context.new(surface).tap do |c| c.line_width = 1 c.set_source_rgb(1, 1, 1) c.rectangle(0, 0, width, height) c.fill # Set black c.set_source_rgb(0, 0, 0) # Draw X and Y axis c.move_to(left, top) c.rel_line_to(0, 8 * distance) c.rel_line_to(25 * distance, 0) c.stroke # Draw indicators on X and Y axis x, y = left, top 8.times do c.move_to(x, y) c.rel_line_to(-indicator_length, 0) c.stroke y += distance end x += distance 26.times do c.move_to(x, y) c.rel_line_to(0, indicator_length) c.stroke x += distance end # Select font c.select_font_face(FONT_FACE, Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_NORMAL) # Set and appropiate font size c.set_font_size(Math.sqrt( (width * height) / 3055.6)) # Draw days on Y axis x, y = (left - 5), (top + distance) DAYS.each do |day| t_ext = c.text_extents(day.to_s) c.move_to(x - indicator_length - t_ext.width, y + t_ext.height / 2) c.show_text(day.to_s) y += distance end # Draw hours on X axis x, y = (left + distance), (top + (7 + 1) * distance + 5) HOURS.each do |hour| t_ext = c.text_extents(hour.to_s) c.move_to(x - t_ext.width / 2 - t_ext.x_bearing, y + indicator_length + t_ext.height / 2) c.show_text(hour.to_s) x += distance end end end
distance()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 52 def distance distance = Math.sqrt((width * height) / 270.5).round if distance % 2 == 1 distance -= 1 end distance end
draw_circle(position, weight)
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 174 def draw_circle(position, weight) x, y = position alpha = (weight.to_f / max_value.to_f) context.set_source_rgba(0, 0, 0, alpha) context.move_to(x, y) context.arc(x, y, weight, 0, 2 * Math::PI) context.fill end
get_weight(number)
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 82 def get_weight(number) return 0 if number.zero? (1..(distance / 2)).to_a.each do |i| if i * i <= number && number < (i + 1) * (i + 1) return i end end if number == max_range return distance/2-1 end nil end
get_x_y_from_day_and_hour(day, hour)
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 76 def get_x_y_from_day_and_hour(day, hour) y = top + (DAYS.index(day.to_s) + 1) * distance x = left + (hour.to_i + 1) * distance [x, y] end
height()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 48 def height (width / 2.75).round(0) end
indicator_length()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 68 def indicator_length height / 20 end
left()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 64 def left (width / 18) + LEFT_PADDING end
max_range()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 60 def max_range (distance / 2)**2 end
max_value()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 107 def max_value all_values.sort.last end
surface()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 111 def surface @surface ||= Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32, width, height) end
top()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 72 def top indicator_length + TOP_PADDING end
width()
click to toggle source
# File lib/birdwatcher/punchcard.rb, line 44 def width WIDTH end