aboutsummaryrefslogtreecommitdiffstats
path: root/internal/chore
diff options
context:
space:
mode:
Diffstat (limited to 'internal/chore')
-rw-r--r--internal/chore/handler.go33
-rw-r--r--internal/chore/model/model.go1
-rw-r--r--internal/chore/repo/repository.go7
-rw-r--r--internal/chore/scheduler.go28
4 files changed, 60 insertions, 9 deletions
diff --git a/internal/chore/handler.go b/internal/chore/handler.go
index bce6d01..5ec8cdd 100644
--- a/internal/chore/handler.go
+++ b/internal/chore/handler.go
@@ -802,14 +802,33 @@ func (h *Handler) completeChore(c *gin.Context) {
})
return
}
+ var nextDueDate *time.Time
+ if chore.FrequencyType == "adaptive" {
+ history, err := h.choreRepo.GetChoreHistoryWithLimit(c, chore.ID, 5)
+ if err != nil {
+ c.JSON(500, gin.H{
+ "error": "Error getting chore history",
+ })
+ return
+ }
+ nextDueDate, err = scheduleAdaptiveNextDueDate(chore, completedDate, history)
+ if err != nil {
+ log.Printf("Error scheduling next due date: %s", err)
+ c.JSON(500, gin.H{
+ "error": "Error scheduling next due date",
+ })
+ return
+ }
- nextDueDate, err := scheduleNextDueDate(chore, completedDate)
- if err != nil {
- log.Printf("Error scheduling next due date: %s", err)
- c.JSON(500, gin.H{
- "error": "Error scheduling next due date",
- })
- return
+ } else {
+ nextDueDate, err = scheduleNextDueDate(chore, completedDate)
+ if err != nil {
+ log.Printf("Error scheduling next due date: %s", err)
+ c.JSON(500, gin.H{
+ "error": "Error scheduling next due date",
+ })
+ return
+ }
}
choreHistory, err := h.choreRepo.GetChoreHistory(c, chore.ID)
if err != nil {
diff --git a/internal/chore/model/model.go b/internal/chore/model/model.go
index 2e7ee90..90f6c29 100644
--- a/internal/chore/model/model.go
+++ b/internal/chore/model/model.go
@@ -80,5 +80,6 @@ type ChoreDetail struct {
LastCompletedDate *time.Time `json:"lastCompletedDate" gorm:"column:last_completed_date"`
LastCompletedBy *int `json:"lastCompletedBy" gorm:"column:last_completed_by"`
TotalCompletedCount int `json:"totalCompletedCount" gorm:"column:total_completed"`
+ Notes *string `json:"notes" gorm:"column:notes"`
CreatedBy int `json:"createdBy" gorm:"column:created_by"`
}
diff --git a/internal/chore/repo/repository.go b/internal/chore/repo/repository.go
index 4eac59c..7284202 100644
--- a/internal/chore/repo/repository.go
+++ b/internal/chore/repo/repository.go
@@ -234,6 +234,7 @@ func (r *ChoreRepository) GetChoreDetailByID(c context.Context, choreID int, cir
chores.assigned_to,
chores.created_by,
recent_history.last_completed_date,
+ recent_history.notes,
recent_history.last_assigned_to as last_completed_by,
COUNT(chore_histories.id) as total_completed`).
Joins("LEFT JOIN chore_histories ON chores.id = chore_histories.chore_id").
@@ -241,7 +242,9 @@ func (r *ChoreRepository) GetChoreDetailByID(c context.Context, choreID int, cir
SELECT
chore_id,
assigned_to AS last_assigned_to,
- completed_at AS last_completed_date
+ completed_at AS last_completed_date,
+ notes
+
FROM chore_histories
WHERE (chore_id, completed_at) IN (
SELECT chore_id, MAX(completed_at)
@@ -250,7 +253,7 @@ func (r *ChoreRepository) GetChoreDetailByID(c context.Context, choreID int, cir
)
) AS recent_history ON chores.id = recent_history.chore_id`).
Where("chores.id = ? and chores.circle_id = ?", choreID, circleID).
- Group("chores.id, recent_history.last_completed_date, recent_history.last_assigned_to").
+ Group("chores.id, recent_history.last_completed_date, recent_history.last_assigned_to, recent_history.notes").
First(&choreDetail).Error; err != nil {
return nil, err
diff --git a/internal/chore/scheduler.go b/internal/chore/scheduler.go
index 55cdf01..c1ff48d 100644
--- a/internal/chore/scheduler.go
+++ b/internal/chore/scheduler.go
@@ -47,6 +47,7 @@ func scheduleNextDueDate(chore *chModel.Chore, completedDate time.Time) (*time.T
} else if chore.FrequencyType == "yearly" {
nextDueDate = baseDate.AddDate(1, 0, 0)
} else if chore.FrequencyType == "adaptive" {
+
// TODO: calculate next due date based on the history of the chore
// calculate the difference between the due date and now in days:
diff := completedDate.UTC().Sub(chore.NextDueDate.UTC())
@@ -129,6 +130,33 @@ func scheduleNextDueDate(chore *chModel.Chore, completedDate time.Time) (*time.T
}
+func scheduleAdaptiveNextDueDate(chore *chModel.Chore, completedDate time.Time, history []*chModel.ChoreHistory) (*time.Time, error) {
+ // will generate due date base on history and the different between the completed date and the due date
+ // the more recent the higher weight
+ if len(history) <= 1 {
+ if chore.NextDueDate != nil {
+ diff := completedDate.UTC().Sub(chore.NextDueDate.UTC())
+ nextDueDate := completedDate.UTC().Add(diff)
+ return &nextDueDate, nil
+ }
+ return nil, nil
+ }
+ var weight float64
+ var totalWeight float64
+ var nextDueDate time.Time
+ for i := 0; i < len(history)-1; i++ {
+ delay := history[i].CompletedAt.UTC().Sub(history[i+1].CompletedAt.UTC()).Seconds()
+ weight = delay * float64(len(history)-i)
+ totalWeight += weight
+ }
+ // calculate the average delay
+ averageDelay := totalWeight / float64(len(history)-1)
+ // calculate the difference between the completed date and the due date
+ nextDueDate = completedDate.UTC().Add(time.Duration(averageDelay) * time.Second)
+
+ return &nextDueDate, nil
+}
+
func RemoveAssigneeAndReassign(chore *chModel.Chore, userID int) {
for i, assignee := range chore.Assignees {
if assignee.UserID == userID {