diff options
author | Özgür Kesim <oec@kesim.org> | 2024-12-01 18:03:55 +0100 |
---|---|---|
committer | Özgür Kesim <oec@kesim.org> | 2024-12-01 18:03:55 +0100 |
commit | d5997c53855cee043788d43e18efca746d0ad1bd (patch) | |
tree | c4b57a06cfebb7b2e9204d1c1b5bdcdcc6832282 /zeitgeist.go | |
parent | 18ea2fa060a81d01a04d1fed5b92fbbae26a0fe2 (diff) |
added ParseString and range support for Totals
Diffstat (limited to 'zeitgeist.go')
-rw-r--r-- | zeitgeist.go | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/zeitgeist.go b/zeitgeist.go index 66ef520..2e99d91 100644 --- a/zeitgeist.go +++ b/zeitgeist.go @@ -99,7 +99,7 @@ func (en Entries) FilterWPTask(wp, task string) Entries { return r } -func (en Entries) Totals() Amount { +func (en Entries) Totals(ymt ...int) Amount { var a Amount for _, e := range en { a += e.Amount @@ -107,6 +107,20 @@ func (en Entries) Totals() Amount { return a } +func (t Timeline) FilterDates(rang ...Date) Entries { + r := Entries{} + for d, e := range t { // TODO: sorted!? + if len(rang) > 0 && d.Before(rang[0]) { + continue + } + if len(rang) > 1 && d.After(rang[1]) { + continue + } + r = append(r, e...) + } + return r +} + func (t Timeline) FilterWPTask(wp, task string) Entries { r := Entries{} for _, e := range t { @@ -124,8 +138,9 @@ func (t Timeline) FilterWP(name string) Entries { } type User struct { - Name string - Type string + Name string + Type string + Blocked map[Date]string } type Workpackage struct { @@ -185,6 +200,10 @@ func (a Date) After(b Date) bool { return (time.Time(a)).After(time.Time(b)) } +func (a Date) Before(b Date) bool { + return (time.Time(a)).Before(time.Time(b)) +} + type Amount float64 const ( @@ -620,15 +639,22 @@ func (p *Project) readTimelogs(dir string) error { var embedFS embed.FS var once sync.Once var templates *template.Template +var funcs = template.FuncMap{ + "ParseDate": func(in string) (Date, error) { + d, e := time.Parse(time.DateOnly, in) + return Date(d), e + }, +} func (p *Project) printReport(name string) { var e error once.Do(func() { + templates = template.New("templates/").Funcs(funcs) if *fl_templates != "" { - templates, e = template.ParseGlob(*fl_templates + "/*.md") + templates, e = templates.ParseGlob(*fl_templates + "/*.md") } else { - templates, e = template.ParseFS(embedFS, "templates/*.md") + templates, e = templates.ParseFS(embedFS, "templates/*.md") } if e != nil { log.Fatalf("Couldn't parse templates: %v\n", e) @@ -668,6 +694,24 @@ func (p *Project) IsBlocked(d Date) bool { return ok } +func (p *Project) IsBlockedForUser(d Date, u string) bool { + user, ok := p.Users[u] + if !ok { + return false + } + _, ok = user.Blocked[d] + return ok +} + +func (p *Project) IsBlockedForAnyUser(d Date) bool { + for _, user := range p.Users { + if _, ok := user.Blocked[d]; ok { + return true + } + } + return false +} + func (f *FullDate) Difference() Amount { return f.Planned.Total() - f.Worked.Total() } @@ -916,7 +960,17 @@ func (t *Totals) Open() Amount { return d } -func (p *Project) TotalWPTask(wp, task string) (to *Totals, e error) { +func (t *Totals) Percent() float64 { + if t.Done < 1 && t.Planned < 1 { + return 0 + } + if t.Planned < 1 { + t.Planned = 1 + } + return float64(t.Done/t.Planned) * 100 +} + +func (p *Project) TotalWPTask(wp, task string, rang ...Date) (to *Totals, e error) { w, ok := p.Workpackages[wp] if !ok { return nil, fmt.Errorf("no such workpackage handle: %q", wp) @@ -927,13 +981,13 @@ func (p *Project) TotalWPTask(wp, task string) (to *Totals, e error) { } to = &Totals{ Budgeted: t.Budget, - Planned: p.Planned.FilterWPTask(wp, task).Total(), - Done: p.Timeline.FilterWPTask(wp, task).Total(), + Planned: p.Planned.FilterDates(rang...).FilterWPTask(wp, task).Total(), + Done: p.Timeline.FilterDates(rang...).FilterWPTask(wp, task).Total(), } return to, nil } -func (p *Project) TotalWP(name string) (tot *WPTotals, e error) { +func (p *Project) TotalWP(name string, rang ...Date) (tot *WPTotals, e error) { wp, ok := p.Workpackages[name] if !ok { return nil, fmt.Errorf("no such workpackage handle: %q", name) @@ -941,8 +995,8 @@ func (p *Project) TotalWP(name string) (tot *WPTotals, e error) { tot = &WPTotals{ Totals: Totals{ Budgeted: wp.TotalBudget(), - Planned: p.Planned.FilterWP(name).Total(), - Done: p.Timeline.FilterWP(name).Total(), + Planned: p.Planned.FilterDates(rang...).FilterWP(name).Total(), + Done: p.Timeline.FilterDates(rang...).FilterWP(name).Total(), }, Tasks: make(map[string]*Totals), } @@ -961,12 +1015,12 @@ type AllTotals struct { WP map[string]*WPTotals } -func (p *Project) Totals() (at *AllTotals) { +func (p *Project) Totals(rang ...Date) (at *AllTotals) { at = &AllTotals{ WP: make(map[string]*WPTotals), } for n := range p.Workpackages { - t, _ := p.TotalWP(n) + t, _ := p.TotalWP(n, rang...) at.WP[n] = t at.Totals.Budgeted += t.Budgeted at.Totals.Planned += t.Planned @@ -1024,11 +1078,13 @@ func (p *Project) ParallelWPTotals(tmpl ...string) ([]string, error) { if len(tmpl) > 0 { tm = tmpl[0] } + if nil == templates.Lookup(tm) { return nil, fmt.Errorf("template %q not found", tm) } totals := p.Totals() + content := [][]string{} for _, name := range slices.Sorted(maps.Keys(totals.WP)) { wpt := totals.WP[name] |