Files
worktimeBot/internal/domain/totals.go
db123 6f7f5878bf
All checks were successful
CI / build (push) Successful in 38s
fix: correct daily work/break calculations and league back button
- ComputeDailyTotals: only assume working from dayStart when first event
  is 'out' (cross-midnight session); otherwise start idle. Fixes inflated
  work/break counts in reports, status, export, burnout, salary, and RPG.
- leagueToggleCallback: add settings back keyboard when RPG is disabled.
- webhook: add graceful HTTP server shutdown on context cancellation.
2026-06-27 23:15:12 +03:30

69 lines
1.8 KiB
Go

package domain
import "sort"
// ComputeDailyTotals calculates the total work and break time from a list of events.
func ComputeDailyTotals(events []Event, minBreakThreshold int64, dayStart, dayEnd int64) DailyTotals {
if len(events) == 0 {
return DailyTotals{}
}
sorted := make([]Event, len(events))
copy(sorted, events)
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].OccurredAt < sorted[j].OccurredAt
})
var totalWork, totalBreak int64
state := StateIdle
var workStart, breakStart int64
if dayStart > 0 && sorted[0].EventType == "out" {
state = StateWorking
workStart = dayStart
} else if sorted[0].EventType == "out" {
state = StateOnBreak
}
for _, e := range sorted {
switch {
case e.EventType == "in" && state == StateIdle:
state = StateWorking
workStart = e.OccurredAt
case e.EventType == "in" && state == StateOnBreak:
breakElapsed := e.OccurredAt - breakStart
if breakElapsed >= minBreakThreshold {
totalBreak += breakElapsed
} else {
totalWork += breakElapsed
}
state = StateWorking
workStart = e.OccurredAt
case e.EventType == "in" && state == StateWorking:
case e.EventType == "out" && state == StateWorking:
totalWork += e.OccurredAt - workStart
state = StateOnBreak
breakStart = e.OccurredAt
case e.EventType == "out" && state == StateOnBreak:
breakStart = e.OccurredAt
case e.EventType == "out" && state == StateIdle:
state = StateOnBreak
breakStart = e.OccurredAt
}
}
if state == StateWorking && dayEnd > 0 {
totalWork += dayEnd - workStart
}
if state == StateOnBreak && dayEnd > 0 {
breakElapsed := dayEnd - breakStart
if breakElapsed >= minBreakThreshold {
totalBreak += breakElapsed
} else {
totalWork += breakElapsed
}
}
return DailyTotals{TotalSeconds: totalWork, BreakSeconds: totalBreak}
}