2019-05-19 20:49:27 +03:00
|
|
|
package services
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/jinzhu/gorm"
|
|
|
|
"github.com/n1try/wakapi/models"
|
|
|
|
)
|
|
|
|
|
|
|
|
type SummaryService struct {
|
|
|
|
Config *models.Config
|
|
|
|
Db *gorm.DB
|
|
|
|
HeartbeatService *HeartbeatService
|
|
|
|
}
|
|
|
|
|
|
|
|
func (srv *SummaryService) GetSummary(from, to time.Time, user *models.User) (*models.Summary, error) {
|
|
|
|
heartbeats, err := srv.HeartbeatService.GetAllWithin(from, to, user)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-05-19 22:00:19 +03:00
|
|
|
types := []uint8{models.SummaryProject, models.SummaryLanguage, models.SummaryEditor, models.SummaryOS}
|
|
|
|
|
|
|
|
var projectItems []models.SummaryItem
|
|
|
|
var languageItems []models.SummaryItem
|
|
|
|
var editorItems []models.SummaryItem
|
|
|
|
var osItems []models.SummaryItem
|
|
|
|
|
|
|
|
c := make(chan models.SummaryItemContainer)
|
|
|
|
for _, t := range types {
|
|
|
|
go srv.aggregateBy(heartbeats, t, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(types); i++ {
|
|
|
|
item := <-c
|
|
|
|
switch item.Type {
|
|
|
|
case models.SummaryProject:
|
|
|
|
projectItems = item.Items
|
|
|
|
case models.SummaryLanguage:
|
|
|
|
languageItems = item.Items
|
|
|
|
case models.SummaryEditor:
|
|
|
|
editorItems = item.Items
|
|
|
|
case models.SummaryOS:
|
|
|
|
osItems = item.Items
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(c)
|
|
|
|
|
2019-05-19 20:49:27 +03:00
|
|
|
summary := &models.Summary{
|
|
|
|
UserID: user.ID,
|
|
|
|
FromTime: &from,
|
|
|
|
ToTime: &to,
|
2019-05-19 22:00:19 +03:00
|
|
|
Projects: projectItems,
|
|
|
|
Languages: languageItems,
|
|
|
|
Editors: editorItems,
|
|
|
|
OperatingSystems: osItems,
|
2019-05-19 20:49:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return summary, nil
|
|
|
|
}
|
|
|
|
|
2019-05-19 22:00:19 +03:00
|
|
|
func (srv *SummaryService) aggregateBy(heartbeats []*models.Heartbeat, summaryType uint8, c chan models.SummaryItemContainer) {
|
2019-05-19 20:49:27 +03:00
|
|
|
durations := make(map[string]time.Duration)
|
|
|
|
|
|
|
|
for i, h := range heartbeats {
|
|
|
|
var key string
|
2019-05-19 22:00:19 +03:00
|
|
|
switch summaryType {
|
2019-05-19 20:49:27 +03:00
|
|
|
case models.SummaryProject:
|
|
|
|
key = h.Project
|
|
|
|
case models.SummaryEditor:
|
|
|
|
key = h.Editor
|
|
|
|
case models.SummaryLanguage:
|
|
|
|
key = h.Language
|
|
|
|
case models.SummaryOS:
|
|
|
|
key = h.OperatingSystem
|
|
|
|
}
|
|
|
|
|
2019-05-20 19:44:16 +03:00
|
|
|
if key == "" {
|
2019-05-21 15:02:04 +03:00
|
|
|
key = "unknown"
|
2019-05-20 19:44:16 +03:00
|
|
|
}
|
|
|
|
|
2019-05-19 20:49:27 +03:00
|
|
|
if _, ok := durations[key]; !ok {
|
|
|
|
durations[key] = time.Duration(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if i == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
timePassed := h.Time.Time().Sub(heartbeats[i-1].Time.Time())
|
|
|
|
timeThresholded := math.Min(float64(timePassed), float64(time.Duration(2)*time.Minute))
|
|
|
|
durations[key] += time.Duration(int64(timeThresholded))
|
|
|
|
}
|
|
|
|
|
|
|
|
items := make([]models.SummaryItem, 0)
|
|
|
|
for k, v := range durations {
|
|
|
|
items = append(items, models.SummaryItem{
|
|
|
|
Key: k,
|
|
|
|
Total: v / time.Second,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-05-19 22:00:19 +03:00
|
|
|
c <- models.SummaryItemContainer{Type: summaryType, Items: items}
|
2019-05-19 20:49:27 +03:00
|
|
|
}
|