# frozen_string_literal: true # Graphs activities by month module Friends class Graph DATE_FORMAT = "%b %Y".freeze # rubocop:disable Style/FormatStringToken # @param activities [Array] a list of activities to graph def initialize(filtered_activities:, all_activities:) @filtered_activities = filtered_activities @all_activities = all_activities return if @all_activities.empty? @start_date = @all_activities.last.date @end_date = @all_activities.first.date end # Prints the graph to STDOUT, with colors. def draw to_h.each do |month, (filtered_count, total_count)| str = "#{month} |" str += Array.new(filtered_count) do |count| Paint["█", color(count)] end.join if total_count > filtered_count str += Array.new(total_count - filtered_count) do |count| Paint["∙", color(filtered_count + count)] end.join + Paint["|", color(total_count + 1)] end puts str end end private # Render the graph as a hash in the format: # # { # "Jan 2015" => [3, 4], # [# filtered activities, # total activities] # "Feb 2015" => [0, 0], # "Mar 2015" => [0, 9] # } # # @return [Hash{String => Integer}] def to_h empty_graph.tap do |graph| @filtered_activities.each do |activity| graph[format_date(activity.date)][0] += 1 end @all_activities.each do |activity| graph[format_date(activity.date)][1] += 1 end end end # Render an empty graph as a hash in the format: # # { # "Jan 2015" => [0, 0] # [# filtered activities, # total activities] # "Feb 2015" => [0, 0] # "Mar 2015" => [0, 0] # } # # @return [Hash{String => Integer}] def empty_graph Hash[(@start_date && @end_date ? (@start_date..@end_date) : []).map do |date| [format_date(date), [0, 0]] end] end # Format a date for use in the graph label # @param date [Date] the date to format # @return [String] def format_date(date) date.strftime(DATE_FORMAT) end # @param x [Integer] the x coordinate we want to color; x >= 0 # @return [Array] the color we should use to paint # a point on the graph at the given x coordinate def color(x) COLORS[x % COLORS.size] end # Originally generated by executing the code in Minitest's Pride plugin (the PrideLOL class), # and then pulling the unique values out and doubling them to create a more even distribution # of colors. COLORS = [ [153, 255, 0], [153, 255, 0], [153, 204, 0], [153, 204, 0], [204, 204, 0], [204, 204, 0], [255, 153, 0], [255, 153, 0], [255, 102, 0], [255, 102, 0], [255, 51, 51], [255, 51, 51], [255, 0, 102], [255, 0, 102], [255, 0, 153], [255, 0, 153], [204, 0, 204], [204, 0, 204], [153, 0, 255], [153, 0, 255], [102, 0, 255], [102, 0, 255], [51, 51, 255], [51, 51, 255], [0, 102, 255], [0, 102, 255], [0, 153, 255], [0, 153, 255], [0, 204, 204], [0, 204, 204], [0, 255, 153], [0, 255, 153], [0, 255, 102], [0, 255, 102], [51, 255, 51], [51, 255, 51], [102, 255, 0], [102, 255, 0] ].freeze private_constant :COLORS end end