worklog/internal/workday/workday.go

202 lines
5.4 KiB
Go

package workday
import (
"encoding/json"
"errors"
"math/rand"
"sort"
"time"
"velvettear/worklog/internal/config"
"velvettear/worklog/internal/database"
"velvettear/worklog/internal/tools"
)
// exported function(s)
func ToCSV(from time.Time, to time.Time, user string) string {
report := getReportHeader()
for _, workday := range getInRange(from, to, user) {
report += "\n" +
workday.Date + ";" +
tools.TimeToHHMMSS(workday.Start) + ";" +
tools.TimeToHHMMSS(workday.Stop) + ";" +
tools.DurationToHHMMSS(workday.Duration) + ";" +
tools.TimeToHHMMSS(workday.Pause.Start) + ";" +
tools.TimeToHHMMSS(workday.Pause.Stop) + ";" +
tools.DurationToHHMMSS(workday.Pause.Duration)
}
return report
}
func ToJSON(from time.Time, to time.Time, user string) (string, error) {
workdays := getInRange(from, to, user)
if len(workdays) == 0 {
return "", nil
}
var jsonWorkdays []workdayJson
for _, workday := range workdays {
workdayJson := workdayJson{
User: user,
Date: workday.Date,
Start: tools.TimeToHHMMSS(workday.Start),
Stop: tools.TimeToHHMMSS(workday.Stop),
Duration: tools.DurationToHHMMSS(workday.Duration),
}
workdayJson.Open = workday.isOpen()
if workday.Pause.Duration > 0 {
pauseJson := pauseJson{
Start: tools.TimeToHHMMSS(workday.Pause.Start),
Stop: tools.TimeToHHMMSS(workday.Pause.Stop),
Duration: tools.DurationToHHMMSS(workday.Pause.Duration),
}
workdayJson.Pause = pauseJson
}
jsonWorkdays = append(jsonWorkdays, workdayJson)
}
bytes, error := json.Marshal(jsonWorkdays)
return string(bytes), error
}
func (workday *Workday) ToJSON(user string) (string, error) {
workdayJson := workdayJson{
User: user,
Date: workday.Date,
Start: tools.TimeToHHMMSS(workday.Start),
Stop: tools.TimeToHHMMSS(workday.Stop),
Duration: tools.DurationToHHMMSS(workday.Duration),
}
workdayJson.Open = workday.isOpen()
if workday.Pause.Duration > 0 {
pauseJson := pauseJson{
Start: tools.TimeToHHMMSS(workday.Pause.Start),
Stop: tools.TimeToHHMMSS(workday.Pause.Stop),
Duration: tools.DurationToHHMMSS(workday.Pause.Duration),
}
workdayJson.Pause = pauseJson
}
bytes, error := json.Marshal(workdayJson)
return string(bytes), error
}
func GetToday(user string) (Workday, error) {
var workday Workday
firstTimestamp := database.GetFirstTimestamp(user, time.Now())
if firstTimestamp.ID == 0 {
return workday, errors.New("no workday for user '" + user + "' started today")
}
workday.Date = tools.TimeToDDMMYYYY(firstTimestamp.Start)
workday.Start = firstTimestamp.Start
workday.Stop = firstTimestamp.End
workday.Duration = workday.Stop.Sub(workday.Start)
if workday.isOpen() {
return workday, nil
}
currentTimestamp := database.GetLastTimestamp(user, time.Now())
workday.Stop = currentTimestamp.End
if workday.Stop == tools.ZeroDate {
workday.Duration = time.Since(workday.Start)
} else {
workday.Duration = workday.Stop.Sub(workday.Start)
}
return workday, nil
}
// unexported function(s)
func getReportHeader() string {
var reportHeader string
for index, header := range config.ReportHeaders() {
if index > 0 {
reportHeader += ";"
}
reportHeader += header
}
return reportHeader
}
func getInRange(from time.Time, to time.Time, user string) []Workday {
return aggregatedTimestampsToWorkdays(database.GetAggregatedTimestamps(from, to, user))
}
func aggregatedTimestampsToWorkdays(aggregatedTimestamps map[string][]database.Timestamp) []Workday {
var workdays []Workday
for key, value := range aggregatedTimestamps {
var tmpStart time.Time
var tmpEnd time.Time
var duration time.Duration
for _, timestamp := range value {
start := timestamp.Start
end := timestamp.End
if tmpStart == tools.ZeroDate || start.Before(tmpStart) {
tmpStart = start
}
if tmpEnd == tools.ZeroDate || end.After(tmpEnd) {
tmpEnd = end
}
duration = tmpEnd.Sub(tmpStart)
}
workday := Workday{
Date: key,
Start: tmpStart,
Stop: tmpEnd,
Duration: duration,
}
workday.insertFakePause()
workdays = append(workdays, workday)
tmpStart = time.Time{}
tmpEnd = time.Time{}
duration = 0
}
sort.Slice(workdays, func(index, comparisonIndex int) bool {
date, _ := tools.DDMMYYToDate(workdays[index].Date)
comparisonDate, _ := tools.DDMMYYToDate(workdays[comparisonIndex].Date)
return date.After(comparisonDate)
})
return workdays
}
func (workday *Workday) isOpen() bool {
return workday.Stop == tools.ZeroDate
}
func (workday *Workday) insertFakePause() {
var pause Pause
deviationStart := rand.Intn(15-(-15)) + (-15)
pause.Start = workday.Start.Add(workday.Duration / 2)
pause.Start = pause.Start.Add(time.Minute * time.Duration(deviationStart))
deviationEnd := rand.Intn(300)
pause.Stop = pause.Start.Add(time.Minute * 30).Add(time.Second * time.Duration(deviationEnd))
pause.Duration = pause.Stop.Sub(pause.Start)
workday.Pause = pause
workday.Stop = workday.Stop.Add(workday.Pause.Duration)
}
// struct(s)
type Workday struct {
Date string
Start time.Time
Stop time.Time
Duration time.Duration
Pause Pause
}
type Pause struct {
Start time.Time
Stop time.Time
Duration time.Duration
}
type workdayJson struct {
User string
Date string
Start string
Stop string
Duration string
Open bool
Pause pauseJson
}
type pauseJson struct {
Start string
Stop string
Duration string
}