github.com/developest/gtm-core@v1.0.4-0.20220111132249-cc80a3372c3f/report/timeline.go (about) 1 // Copyright 2016 Michael Schenk. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package report 6 7 import ( 8 "sort" 9 "strconv" 10 "time" 11 12 "github.com/DEVELOPEST/gtm-core/util" 13 ) 14 15 type timelineCommitEntries []timelineCommitEntry 16 17 type timelineCommitEntry struct { 18 Day string 19 Total int 20 Commits [24]int 21 } 22 23 func (t *timelineCommitEntry) inc(hour int) { 24 t.Total++ 25 t.Commits[hour]++ 26 } 27 28 func (t timelineCommitEntries) HourMaxCommits() int { 29 max := 0 30 for _, entry := range t { 31 for _, commits := range entry.Commits { 32 if commits > max { 33 max = commits 34 } 35 } 36 } 37 return max 38 } 39 40 func (t timelineCommitEntries) Total() int { 41 total := 0 42 for _, e := range t { 43 total += e.Total 44 } 45 return total 46 } 47 48 func (c commitNoteDetails) timelineCommits() (timelineCommitEntries, error) { 49 timelineMap := map[string]timelineCommitEntry{} 50 timeline := []timelineCommitEntry{} 51 for _, n := range c { 52 t := n.When 53 day := t.Format("2006-01-02") 54 hour, err := strconv.Atoi(t.Format("15")) 55 if err != nil { 56 return timelineCommitEntries{}, err 57 } 58 if entry, ok := timelineMap[day]; !ok { 59 var commits [24]int 60 commits[hour] = 1 61 timelineMap[day] = timelineCommitEntry{Day: t.Format("Mon Jan 02"), Commits: commits, Total: 1} 62 } else { 63 entry.inc(hour) 64 timelineMap[day] = entry 65 } 66 } 67 68 keys := make([]string, 0, len(timelineMap)) 69 for key := range timelineMap { 70 keys = append(keys, key) 71 } 72 sort.Sort(sort.StringSlice(keys)) 73 for _, k := range keys { 74 timeline = append(timeline, timelineMap[k]) 75 } 76 77 return timeline, nil 78 } 79 80 func (c commitNoteDetails) timeline() (timelineEntries, error) { 81 timelineMap := map[string]timelineEntry{} 82 timeline := []timelineEntry{} 83 for _, n := range c { 84 for _, f := range n.Note.Files { 85 for epoch, secs := range f.Timeline { 86 t := time.Unix(epoch, 0) 87 day := t.Format("2006-01-02") 88 hour, err := strconv.Atoi(t.Format("15")) 89 if err != nil { 90 return timelineEntries{}, err 91 } 92 if entry, ok := timelineMap[day]; !ok { 93 var hours [24]int 94 hours[hour] = secs 95 timelineMap[day] = timelineEntry{Day: t.Format("Mon Jan 02"), Hours: hours, Seconds: secs} 96 } else { 97 entry.add(secs, hour) 98 timelineMap[day] = entry 99 } 100 } 101 } 102 } 103 104 keys := make([]string, 0, len(timelineMap)) 105 for key := range timelineMap { 106 keys = append(keys, key) 107 } 108 sort.Sort(sort.StringSlice(keys)) 109 for _, k := range keys { 110 timeline = append(timeline, timelineMap[k]) 111 } 112 113 return timeline, nil 114 } 115 116 type timelineEntries []timelineEntry 117 118 func (t timelineEntries) Duration() string { 119 total := 0 120 for _, entry := range t { 121 total += entry.Seconds 122 } 123 return util.FormatDuration(total) 124 } 125 126 func (t timelineEntries) HourMaxSeconds() int { 127 // Default to number of seconds in a hour 128 // Actual max can be much higher when reporting 129 // across multiple projects and users 130 max := 3600 131 for _, entry := range t { 132 for _, secs := range entry.Hours { 133 if secs > max { 134 max = secs 135 } 136 } 137 } 138 return max 139 } 140 141 type timelineEntry struct { 142 Day string 143 Seconds int 144 Hours [24]int 145 } 146 147 func (t *timelineEntry) add(s int, hour int) { 148 t.Seconds += s 149 t.Hours[hour] += s 150 } 151 152 func (t *timelineEntry) Duration() string { 153 return util.FormatDuration(t.Seconds) 154 }