internal/httpd/activity.go

v1.33.0
gitbay/internal/httpd/activity.go history · blame · raw

79 lines · 2043 bytes

 1package httpd
 2
 3import "time"
 4
 5// activityDay is one cell of the graph; Level buckets Count into the five
 6// intensity classes the stylesheet colors.
 7type activityDay struct {
 8	Date  string
 9	Count int
10	Level int  // 0..4
11	Pad   bool // before the range start / after today
12}
13
14// activityWeek is one column of the graph: 7 days, Sunday first, plus the
15// month label to show above it (empty for most weeks).
16type activityWeek struct {
17	Days  []activityDay
18	Month string
19}
20
21// activityGrid lays a day->count map into 53 week columns ending today,
22// GitHub-style: columns are weeks, rows Sunday..Saturday. Each week whose
23// first non-pad day falls within the first 7 days of a month, and whose
24// month differs from the last labelled week, carries that month's
25// three-letter name.
26func activityGrid(counts map[string]int) ([]activityWeek, int) {
27	today := time.Now().UTC()
28	// End the grid on the Saturday of the current week.
29	end := today.AddDate(0, 0, int(time.Saturday-today.Weekday()))
30	start := end.AddDate(0, 0, -53*7+1) // a Sunday, 53 columns back
31
32	total := 0
33	var weeks []activityWeek
34	prevMonth := ""
35	for d := start; !d.After(end); d = d.AddDate(0, 0, 7) {
36		var days []activityDay
37		var firstDay time.Time
38		haveFirst := false
39		for i := 0; i < 7; i++ {
40			day := d.AddDate(0, 0, i)
41			key := day.Format("2006-01-02")
42			if day.After(today) {
43				days = append(days, activityDay{Date: key, Pad: true})
44				continue
45			}
46			if !haveFirst {
47				firstDay = day
48				haveFirst = true
49			}
50			n := counts[key]
51			total += n
52			days = append(days, activityDay{Date: key, Count: n, Level: activityLevel(n)})
53		}
54		month := ""
55		if haveFirst && firstDay.Day() <= 7 {
56			if name := firstDay.Month().String()[:3]; name != prevMonth {
57				month = name
58				prevMonth = name
59			}
60		}
61		weeks = append(weeks, activityWeek{Days: days, Month: month})
62	}
63	return weeks, total
64}
65
66func activityLevel(n int) int {
67	switch {
68	case n == 0:
69		return 0
70	case n <= 2:
71		return 1
72	case n <= 5:
73		return 2
74	case n <= 9:
75		return 3
76	default:
77		return 4
78	}
79}