▍ humdrum codex / ticktock v0.0.2
license AGPL-3.0
1.3 KB raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
55
56
57
58
59
60
package day

import (
	"fmt"
	"time"

	"ticktock/internal/store"
)

// fmtDur renders a duration like tock's summaries: "1h37m", "50m", "0m".
func fmtDur(d time.Duration) string {
	m := int(d.Minutes())
	h, m := m/60, m%60
	if h > 0 {
		return fmt.Sprintf("%dh%dm", h, m)
	}
	return fmt.Sprintf("%dm", m)
}

// fmtTockDur renders the table's Duration cell like tock list: "51m0s", "1h37m0s".
func fmtTockDur(d time.Duration) string {
	s := int(d.Seconds())
	h, s := s/3600, s%3600
	m, s := s/60, s%60
	if h > 0 {
		return fmt.Sprintf("%dh%dm%ds", h, m, s)
	}
	return fmt.Sprintf("%dm%ds", m, s)
}

func fmtRange(e store.Entry) string {
	end := "  …  "
	if !e.Running() {
		end = e.End.Format("15:04")
	}
	return e.Start.Format("15:04") + " - " + end
}

// ProjectTotal is one project's summed duration for the day.
type ProjectTotal struct {
	Project string
	Total   time.Duration
}

// Totals sums per-project and grand-total durations, preserving first-seen order.
func Totals(es []store.Entry) ([]ProjectTotal, time.Duration) {
	idx := map[string]int{}
	var out []ProjectTotal
	var grand time.Duration
	for _, e := range es {
		grand += e.Duration
		if i, ok := idx[e.Project]; ok {
			out[i].Total += e.Duration
			continue
		}
		idx[e.Project] = len(out)
		out = append(out, ProjectTotal{Project: e.Project, Total: e.Duration})
	}
	return out, grand
}