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.

88 lines
1.9 KiB

4 years ago
4 years ago
4 years ago
  1. package services
  2. import (
  3. "context"
  4. "github.com/gisle/stufflog/database"
  5. "github.com/gisle/stufflog/models"
  6. "github.com/gisle/stufflog/slerrors"
  7. "time"
  8. )
  9. // ScoringService scores activities. It cares not for users.
  10. type ScoringService struct {
  11. db database.Database
  12. }
  13. func (s *ScoringService) ScoreOne(ctx context.Context, period models.Period, log models.Log) (*models.Score, error) {
  14. return s.scoreOne(ctx, period, log)
  15. }
  16. func (s *ScoringService) scoreOne(ctx context.Context, period models.Period, log models.Log) (*models.Score, error) {
  17. goal := period.Goal(log.GoalID)
  18. if goal == nil {
  19. return nil, slerrors.NotFound("Goal")
  20. }
  21. activity, err := s.db.Activities().FindID(ctx, goal.ActivityID)
  22. if err != nil || activity.UserID != period.UserID {
  23. return nil, slerrors.NotFound("Goal's Activity")
  24. }
  25. subActivity := activity.SubActivity(log.SubActivityID)
  26. if subActivity == nil {
  27. return nil, slerrors.NotFound("Goal's Sub-Activity")
  28. }
  29. score := models.Score{
  30. ActivityScore: subActivity.Value,
  31. Amount: log.Amount,
  32. }
  33. if activity.DailyBonus > 0 {
  34. isFirst := true
  35. for _, log2 := range period.Logs {
  36. if log2.Date.Local().Truncate(time.Hour*24) != log.Date.Local().Truncate(time.Hour*24) {
  37. continue
  38. }
  39. if log2.ID == log.ID {
  40. break
  41. }
  42. if log2.GoalID == log.GoalID {
  43. isFirst = false
  44. break
  45. }
  46. }
  47. if isFirst {
  48. score.DailyBonus = activity.DailyBonus
  49. }
  50. }
  51. score.Calc()
  52. return &score, nil
  53. }
  54. func (s *ScoringService) ScoreAll(ctx context.Context, period models.Period) (*models.Period, error) {
  55. period = *period.Copy()
  56. for i, log := range period.Logs {
  57. score, err := s.scoreOne(ctx, period, log)
  58. if err != nil {
  59. return nil, err
  60. }
  61. period.Logs[i].Score = score
  62. }
  63. err := s.db.Periods().Insert(ctx, period)
  64. if err != nil {
  65. return nil, err
  66. }
  67. return &period, nil
  68. }
  69. func NewScoringService(db database.Database) *ScoringService {
  70. return &ScoringService{db: db}
  71. }