Plan stuff. Log stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

98 lines
2.1 KiB

package services
import (
"context"
"github.com/gisle/stufflog/database"
"github.com/gisle/stufflog/models"
"github.com/gisle/stufflog/slerrors"
"time"
)
// ScoringService scores activities. It cares not for users.
type ScoringService struct {
db database.Database
}
func (s *ScoringService) ScoreOne(ctx context.Context, period models.Period, log models.PeriodLog) (*models.Score, error) {
return s.scoreOne(ctx, period, log)
}
func (s *ScoringService) scoreOne(ctx context.Context, period models.Period, log models.PeriodLog) (*models.Score, error) {
goal := period.Goal(log.GoalID)
if goal == nil {
return nil, slerrors.NotFound("Goal")
}
activity, err := s.db.Activities().FindID(ctx, goal.ActivityID)
if err != nil || activity.UserID != period.UserID {
return nil, slerrors.NotFound("Goal's Activity")
}
subActivity := activity.SubActivity(log.SubActivityID)
if subActivity == nil {
return nil, slerrors.NotFound("Goal's Sub-Activity")
}
score := models.Score{
ActivityScore: subActivity.Value,
Amount: log.Amount,
}
if log.SubGoalID != "" {
subGoal := goal.SubGoal(log.SubGoalID)
if subGoal == nil {
return nil, slerrors.NotFound("Sub-Goal")
}
multiplier := subGoal.Multiplier
score.SubGoalMultiplier = &multiplier
}
if activity.DailyBonus > 0 {
isFirst := true
for _, log2 := range period.Logs {
if log2.Date.Local().Truncate(time.Hour*24) != log.Date.Local().Truncate(time.Hour*24) {
continue
}
if log2.ID == log.ID {
break
}
if log2.GoalID == log.GoalID {
isFirst = false
break
}
}
if isFirst {
score.DailyBonus = activity.DailyBonus
}
}
score.Calc()
return &score, nil
}
func (s *ScoringService) ScoreAll(ctx context.Context, period models.Period) (*models.Period, error) {
period = *period.Copy()
for i, log := range period.Logs {
score, err := s.scoreOne(ctx, period, log)
if err != nil {
return nil, err
}
period.Logs[i].Score = score
}
err := s.db.Periods().Insert(ctx, period)
if err != nil {
return nil, err
}
return &period, nil
}
func NewScoringService(db database.Database) *ScoringService {
return &ScoringService{db: db}
}