lib/dates2svg.rb in dates2svg-0.0.1.beta1 vs lib/dates2svg.rb in dates2svg-0.0.1.beta2

- old
+ new

@@ -1,111 +1,120 @@ require "dates2svg/version" class Dates2SVG - BOX_SIZE = 15 - BORDER = 1 - BOX_WITH_BORDER = (BOX_SIZE + BORDER) + attr_reader :options def initialize(dates, options={}) @dates = dates @options = options + process_options parse_dates + @options[:color_range] = color_range + @options[:max] = max end - - def parse_dates - @dates.map do |date| - date_from_facet_value(date) - end.sort do |a, b| - a.year.to_i <=> b.year.to_i - end.group_by(&:year).each do |year, dates| - years << Dates2SVG::Year.new(year, dates) - end - end - def date_from_facet_value(facet) - facet.value[/^(\d{4})-(\d{2})-(\d{2})/] - Dates2SVG::DateWithValue.new(:year => $1, :month => $2, :day => $3, :hits => facet.hits) - end - def years @years ||= [] end def max @max ||= years.map{|year| year.months.map{|month| month.hits} }.flatten.max end def color_range - self.class.color_range(@options.merge(:max => @max)) + max_hits = max || 3000 + section = (max_hits) / (@options[:color_options].length - 1) + colors = {} + ranges = [[0]] + + i = 0 + (@options[:color_options].length - 1).times do + if i == 0 + ranges << (1..(section * 1)) + elsif ((i+1) == (@options[:color_options].length - 1)) + ranges << (((section * i) + 1)..max_hits) + else + ranges << (((section * i) + 1)..(section * (i + 1))) + end + i = i+1 + end + @options[:color_options].each_with_index do |color, index| + unless ranges[index].is_a?(Range) and [ranges[index].first, ranges[index].last].include?(0) + colors[ranges[index]] = color + end + end + colors end - - def color_options - @options[:color_options] || self.class.color_options - end - + def to_svg svg = "" # + 35 and +50 gives us the space for the year month text - svg << "<svg height='#{(12 * BOX_WITH_BORDER) + 35}' width='#{(all_years.to_a.length * BOX_WITH_BORDER) + 50}'>" + svg << "<svg height='#{(12 * @options[:box_with_border]) + 35}' width='#{(all_years.to_a.length * @options[:box_with_border]) + 50}'>" svg << "<g transform='translate(20,35)'>" all_years.each_with_index do |year, index| selected_years = years.select{|y| y.year.to_i == year.to_i } unless selected_years.length == 0 - svg << selected_years.first.to_svg(@options.merge(:index => index, :max => max)) + svg << selected_years.first.to_svg(:index => index) else - svg << Dates2SVG::Year.new(year, []).to_svg(@options.merge(:index => index, :max => max)) + svg << Dates2SVG::Year.new(year, [], @options).to_svg(:index => index) end end svg << calendar_year_listing svg << calendar_month_listing svg << "</g>" svg << "</svg>" end - def self.color_range(options={}) - max_hits = options[:max] || 3000 - section = (max_hits) / 5 - colors = {} - color_options = options[:color_options] || self.color_options - ranges = [[0], (1..(section * 1)), - (((section * 1) + 1)..(section * 2)), - (((section * 2) + 1)..(section * 3)), - (((section * 3) + 1)..(section * 4)), - (((section * 4) + 1)..max_hits)] - color_options.each_with_index do |color, index| - unless ranges[index].is_a?(Range) and [ranges[index].first, ranges[index].last].include?(0) - colors[ranges[index]] = color - end + private + + def parse_dates + @dates.map do |date| + date_from_facet_value(date) + end.sort do |a, b| + a.year.to_i <=> b.year.to_i + end.group_by(&:year).each do |year, dates| + years << Dates2SVG::Year.new(year, dates, @options) end - colors end - - def self.color_options(options={}) - options[:color_options] || ["#EEEEEE", "#330000", "#660000", "#990000", "#CC0000", "#FF0000"] + + def date_from_facet_value(facet) + facet.value[/^(\d{4})-(\d{2})-(\d{2})/] + Dates2SVG::DateWithValue.new(:year => $1, :month => $2, :day => $3, :hits => facet.hits) end - - private - + def all_years @options[:year_range] || years.map{|y| y.year } end def calendar_year_listing svg = "" all_years.each_with_index do |year, index| - svg << "<text x='3' y='#{(BOX_WITH_BORDER * index) + 20}' transform='rotate(-90)' class='year'>#{year}</text>" + svg << "<text x='3' y='#{(@options[:box_with_border] * index) + 20}' transform='rotate(-90)' class='year'>#{year}</text>" end svg end def calendar_month_listing svg = "" ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", " Oct", "Nov", "Dec"].each_with_index do |month, index| - svg << "<text text-anchor='middle' class='cmonth' dx='0' dy='#{(BOX_WITH_BORDER * index) + 10}'>#{month}</text>" + svg << "<text text-anchor='middle' class='cmonth' dx='0' dy='#{(@options[:box_with_border] * index) + 10}'>#{month}</text>" end svg end + def process_options + @options = self.class.default_options.merge(@options) + @options[:box_with_border] = (@options[:box_size].to_i + @options[:border].to_i) + end + + def self.default_options + {:color_options => ["#EEEEEE", "#330000", "#660000", "#990000", "#CC0000", "#FF0000"], + :box_size => 15, + :border => 1, + :box_with_border => nil + } + end + class DateWithValue attr_reader :year, :month, :day, :hits def initialize(ops={}) @year = ops[:year] @month = ops[:month] @@ -114,80 +123,82 @@ end end class Year attr_reader :year - def initialize(year, dates) + def initialize(year, dates, options={}) @year = year @dates = dates + @options = options parse_dates end - def parse_dates - @dates.sort do |a, b| - a.month.to_i <=> b.month.to_i - end.group_by(&:month).map do |month, dates| - months << Dates2SVG::Month.new(@year, month, dates) - end - end - def months @months ||= [] end def to_svg(options={}) svg = "" - svg << "<g transform='translate(#{(BOX_WITH_BORDER * options[:index]) + 12},0)'>" + svg << "<g transform='translate(#{(@options[:box_with_border] * options[:index]) + 12},0)'>" all_months.each_with_index do |month, index| unless months.select{|m| m.month == month}.length == 0 - svg << months.select{|m| m.month == month}.first.to_svg(options.merge(:index => index)) + svg << months.select{|m| m.month == month}.first.to_svg(:index => index) else - svg << Dates2SVG::Month.new(@year, month, []).to_svg(options.merge(:index => index)) + svg << Dates2SVG::Month.new(@year, month, [], @options).to_svg(:index => index) end end svg << "</g>" end private + def parse_dates + @dates.sort do |a, b| + a.month.to_i <=> b.month.to_i + end.group_by(&:month).map do |month, dates| + months << Dates2SVG::Month.new(@year, month, dates, @options) + end + end + def all_months ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"] end end class Month attr_reader :year, :month - def initialize(year, month, dates) + def initialize(year, month, dates, options={}) @year = year @month = month @dates = dates + @options = options end def hits @hits ||= (@dates.map{|d| d.hits.to_i }.inject(:+) || 0) end def to_svg(options={}) svg = "" - svg << "<rect data-hits='#{hits}' data-year='#{@year}' data-month='#{@month}' class='month' width='#{BOX_SIZE}' height='#{BOX_SIZE}' y='#{BOX_WITH_BORDER * options[:index]}' style='fill: #{color(options)};'>" + svg << "<rect data-hits='#{hits}' data-year='#{@year}' data-month='#{@month}' class='month' width='#{@options[:box_size]}' height='#{@options[:box_size]}' y='#{@options[:box_with_border] * options[:index]}' style='fill: #{color};'>" svg << "<title>#{hits} hits on #{@year}-#{@month}</title>" svg << "</rect>" end private - def color(options={}) - max_hits = options[:max] || 3000 + def color + max_hits = @options[:max] || 3000 section = (max_hits / 5) max = section * 5 - return Dates2SVG.color_options(options).last if hits > max - colors = Dates2SVG.color_range(options) + return @options[:color_options].last if hits > max + colors = @options[:color_range] begin # .first turns the hash into an array and .last gets the value colors.select{|k,v| k.include?(hits) }.first.last rescue - Dates2SVG.color_options(options).first + @options[:color_options].first end end end end