Files
worktimeBot/internal/bot/totals.go

81 lines
1.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bot
import (
"sort"
"worktimeBot/internal/db"
)
type State int
const (
StateIdle State = iota
StateWorking
StateOnBreak
)
// DailyTotals holds aggregated times for a single day.
type DailyTotals struct {
TotalSeconds int64
BreakSeconds int64
PairCount int
}
// ComputeDailyTotals pairs events with break inference.
// Multiout sequences: first out ends work, second out starts break,
// next in ends break, next out ends work, etc.
func ComputeDailyTotals(events []db.Event) DailyTotals {
if len(events) == 0 {
return DailyTotals{}
}
sorted := make([]db.Event, len(events))
copy(sorted, events)
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].OccurredAt < sorted[j].OccurredAt
})
var workTotal, breakTotal int64
var workStart, breakStart int64
pairs := 0
state := StateIdle
for _, e := range sorted {
switch {
case e.EventType == "in":
switch state {
case StateIdle, StateOnBreak:
if state == StateOnBreak {
breakTotal += e.OccurredAt - breakStart
breakStart = 0
}
workStart = e.OccurredAt
state = StateWorking
// Working → ignore duplicate in (shouldn't happen)
case StateWorking:
// already working, ignore
}
case e.EventType == "out":
switch state {
case StateWorking:
// End of work period
workTotal += e.OccurredAt - workStart
workStart = 0
pairs++
state = StateIdle
case StateIdle:
// Second consecutive out → break start
breakStart = e.OccurredAt
state = StateOnBreak
case StateOnBreak:
// Duplicate break start ignore
}
}
}
return DailyTotals{
TotalSeconds: workTotal,
BreakSeconds: breakTotal,
PairCount: pairs,
}
}