Class: ActivityGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/activity_graph.rb

Overview

Renders a GitHub-style ASCII activity heatmap for worklog entries. Accepts an array of DailyLog objects and produces a 53-column × 7-row grid where each cell represents one day and darker (brighter) color means more activity.

Examples:

graph = ActivityGraph.new(storage.all_days)
puts graph.render

Constant Summary collapse

DAYS_OF_WEEK =
%w[Mon Tue Wed Thu Fri Sat Sun].freeze
NUM_WEEKS =

Number of weeks to display (approx. one year).

53
MIN_MONTH_GAP =

Minimum column distance between consecutive month labels to prevent overlap.

3

Instance Method Summary collapse

Constructor Details

#initialize(daily_logs) ⇒ ActivityGraph

Returns a new instance of ActivityGraph.



22
23
24
# File 'lib/activity_graph.rb', line 22

def initialize(daily_logs)
  @daily_logs = Array(daily_logs)
end

Instance Method Details

#renderString

Render the activity graph as a printable multi-line string.

Returns:

  • (String)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/activity_graph.rb', line 28

def render
  counts    = count_by_date
  today     = Date.today
  start_date = week_start(today - ((NUM_WEEKS * 7) - 1))
  weeks      = build_weeks(start_date, today)
  max_count  = counts.values.max || 0

  lines = []
  lines << "  #{Rainbow('Activity — past year').bold}"
  lines << ''
  lines << month_header(weeks)

  DAYS_OF_WEEK.each_with_index do |day_name, day_idx|
    cells = weeks.map do |week|
      date = week[day_idx]
      next '  ' if date > today

      count = counts[date] || 0
      "#{colored_block(intensity_level(count, max_count))} "
    end
    lines << "#{day_name} #{cells.join}"
  end

  lines << ''
  lines << legend
  lines.join("\n")
end