package app import ( "context" "fmt" "sort" "strconv" "strings" "time" "cnb.cool/looc/git-cnb/git" ui "cnb.cool/looc/git-cnb/ui" "github.com/spf13/cobra" ) type Week struct { Week int64 Commits int } type User struct { User string Commits int } var StatsCmd = &cobra.Command{ Use: "stats", Short: "print stats information of this repo", Long: "print stats information of this repo", Run: func(cmd *cobra.Command, args []string) { Stats(cmd.Context()) }, } func Stats(ctx context.Context) { lines, err := git.GetCommits() if err != nil { ui.ErrorWithExit(err.Error()) } todayWeek := getStartOfWeek(time.Now()) weeklyMap := generateLastWeeks(todayWeek, 80) userMap := make(map[string]int) for _, v := range lines { s := strings.Split(v, ";") timeStr := s[0] userStr := s[1] userMap[strings.Trim(userStr, "'")]++ timestamp, err := strconv.ParseInt(strings.Trim(timeStr, "'"), 10, 64) if err != nil { ui.Error(err.Error()) continue } weekKey := getStartOfWeek(time.Unix(timestamp, 0)) if _, ok := weeklyMap[weekKey]; !ok { continue } weeklyMap[weekKey]++ } ui.InitDashBoard() drawUserRanking(userMap) drawCommitTrendLine(weeklyMap) ui.DrawDashBoard() } // 获取自然周的第一天(周一) func getStartOfWeek(t time.Time) int64 { weekday := t.Weekday() if weekday == time.Sunday { weekday = 7 } w := fmt.Sprintf("%s 00:00:00", t.AddDate(0, 0, -int(weekday)+1).Format("2006-01-02")) dt, _ := time.Parse("2006-01-02 15:04:05", w) return dt.Unix() } func generateLastWeeks(unixTimestamp int64, limit int) map[int64]int { var t time.Time t = time.Unix(unixTimestamp, 0) m := make(map[int64]int) for i := 0; i < limit; i++ { m[t.Unix()] = 0 t = t.AddDate(0, 0, -7) } return m } func drawUserRanking(userMap map[string]int) { userList := make([]User, 0, len(userMap)) for k, v := range userMap { userList = append(userList, User{ User: k, Commits: v, }) } sort.Slice(userList, func(i, j int) bool { return userList[i].Commits > userList[j].Commits }) count := len(userList) if count > 13 { count = 13 } list := make([]string, 0, count) for _, v := range userList[:count] { item := fmt.Sprintf("[%d] %s", v.Commits, v.User) list = append(list, item) } position := ui.Position{ X: 0, Y: 0, Width: 30, Height: 15, } ui.ListChart("历史提交榜", position, list) } func drawCommitTrendLine(weeklyMap map[int64]int) { list := make([]Week, 0, len(weeklyMap)) for k, v := range weeklyMap { list = append(list, Week{ Week: k, Commits: v, }) } sort.Slice(list, func(i, j int) bool { return list[i].Week < list[j].Week }) data := make([]float64, 0, len(weeklyMap)) for _, v := range list { data = append(data, float64(v.Commits)) } position := ui.Position{ X: 30, Y: 0, Width: 120, Height: 15, } ui.LineChart("过去 80 周的提交曲线", position, data) }