summaryrefslogtreecommitdiff
path: root/internal/schedule/stats.go
blob: 172272fe984931ce7f2c0dfee021b1025251c93d (plain)
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package schedule

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"codeberg.org/snonux/gos/internal/entry"
	"codeberg.org/snonux/gos/internal/oi"
	"codeberg.org/snonux/gos/internal/timestamp"
)

// Posting stats
type stats struct {
	posted            int
	queued            int
	sinceDays         float64
	postsPerDay       float64
	postsPerDayTarget float64
}

func (s stats) String() string {
	return fmt.Sprintf("posted:%d,queued:%d,sinceDays:%v,postsPerDay:%v >? postsPerDayTarget:%v",
		s.posted, s.queued, s.sinceDays, s.postsPerDay, s.postsPerDayTarget,
	)
}

func newStats(dir string, lookback time.Duration, target int) (stats, error) {
	stats := stats{postsPerDayTarget: float64(target) / 7}

	if err := stats.gatherPostedStats(dir, pastTime(lookback)); err != nil {
		return stats, err
	}
	if err := stats.gatherQueuedStats(dir); err != nil {
		return stats, err
	}

	return stats, nil
}

func (s stats) targetHit() bool {
	return s.postsPerDay >= s.postsPerDayTarget
}

func (s *stats) gatherPostedStats(dir string, lookbackTime time.Time) error {
	var (
		now    time.Time = timestamp.NowTime()
		oldest time.Time = now
	)

	err := oi.TraverseDir(dir, func(file os.DirEntry) error {
		filePath := filepath.Join(dir, file.Name())
		ent, err := entry.New(filePath)
		if err != nil {
			return err
		}
		if ent.State != entry.Posted || ent.Time.Before(lookbackTime) {
			return nil
		}
		if ent.Time.Before(oldest) {
			oldest = ent.Time
		}
		s.posted++
		return nil
	})
	if err != nil {
		return err
	}

	since := now.Sub(oldest)
	s.sinceDays = since.Abs().Hours() / 24
	s.postsPerDay = float64(s.posted) / float64(s.sinceDays)
	return nil
}

func (s *stats) gatherQueuedStats(dir string) error {
	var firstQueuedPath string

	err := oi.TraverseDir(dir, func(file os.DirEntry) error {
		filePath := filepath.Join(dir, file.Name())
		ent, err := entry.New(filePath)
		if err != nil {
			return err
		}
		if ent.State == entry.Queued {
			if firstQueuedPath == "" {
				firstQueuedPath = filePath
			}
			s.queued++
		}
		return nil
	})

	return err
}

func pastTime(duration time.Duration) time.Time {
	return timestamp.NowTime().Add(-duration)
}