summaryrefslogtreecommitdiff
path: root/zeitgeist.go
diff options
context:
space:
mode:
Diffstat (limited to 'zeitgeist.go')
-rw-r--r--zeitgeist.go69
1 files changed, 67 insertions, 2 deletions
diff --git a/zeitgeist.go b/zeitgeist.go
index e20ad35..811de40 100644
--- a/zeitgeist.go
+++ b/zeitgeist.go
@@ -64,6 +64,32 @@ func (en Entries) WPs() string {
return strings.Join(wps, ", ")
}
+func (en Entries) FilterWP(name string) Entries {
+ r := Entries{}
+ for _, e := range en {
+ if name == e.WP {
+ r = append(r, e)
+ }
+ }
+ return r
+}
+
+func (en Entries) Totals() Amount {
+ var a Amount
+ for _, e := range en {
+ a += e.Amount
+ }
+ return a
+}
+
+func (t Timeline) FilterWP(name string) Entries {
+ r := Entries{}
+ for _, entries := range t {
+ r = append(r, entries.FilterWP(name)...)
+ }
+ return r
+}
+
type User struct {
Name string
Type string
@@ -78,6 +104,14 @@ type Workpackage struct {
Tasks map[string]Task
}
+func (wp *Workpackage) TotalBudget() Amount {
+ var a Amount
+ for _, t := range wp.Tasks {
+ a += t.Budget
+ }
+ return a
+}
+
type Date time.Time
func (d Date) IsWorkday() bool {
@@ -292,7 +326,7 @@ func (p *Project) readPlans(dir string) error {
} else {
r[0], e = time.Parse("2006-01", parts[0])
if e == nil {
- slog.Info("Month found", "date", parts[0])
+ slog.Debug("Month found", "date", parts[0])
r[1] = r[0].AddDate(0, 1, 0)
isrange = true
} else {
@@ -310,7 +344,7 @@ func (p *Project) readPlans(dir string) error {
if r[0].Equal(r[1]) || r[0].After(r[1]) {
return fmt.Errorf("file %q, line %d: invalid range: %s", name, nr, parts[0])
}
- slog.Info("Found range", "start", r[0], "end", r[1])
+ slog.Debug("Found range", "start", r[0], "end", r[1])
isrange = true
}
}
@@ -712,3 +746,34 @@ func (p *Project) Calendars() map[int]string {
}
return r
}
+
+type Totals struct {
+ Budgeted Amount
+ Planned Amount
+ Actual Amount
+}
+
+func (t *Totals) Unaccounted() Amount {
+ return t.Budgeted - t.Planned
+}
+
+func (p *Project) TotalWP(name string) (t *Totals, e error) {
+ wp, ok := p.Workpackages[name]
+ if !ok {
+ return nil, fmt.Errorf("no such workpackage handle: %q", name)
+ }
+ t = &Totals{
+ Budgeted: wp.TotalBudget(),
+ Planned: p.Planned.FilterWP(name).Total(),
+ Actual: p.Timeline.FilterWP(name).Total(),
+ }
+ return t, nil
+}
+
+func (p *Project) Totals() (t map[string]*Totals) {
+ t = make(map[string]*Totals)
+ for n := range p.Workpackages {
+ t[n], _ = p.TotalWP(n)
+ }
+ return t
+}