This commit is contained in:
Erik Winter 2024-12-01 11:51:43 +01:00
parent 3f0bd4e047
commit f87d979582
6 changed files with 120 additions and 14 deletions

View File

@ -51,7 +51,9 @@ func (e *EventBody) UnmarshalJSON(data []byte) error {
} }
type Event struct { type Event struct {
ID string `json:"id"` ID string `json:"id"`
Recurrer *Recur `json:"recurrer"`
RecurNext time.Time `json:"recurNext"`
EventBody EventBody
} }
@ -66,6 +68,8 @@ func NewEvent(i Item) (Event, error) {
} }
e.ID = i.ID e.ID = i.ID
e.Recurrer = i.Recurrer
e.RecurNext = i.RecurNext
return e, nil return e, nil
} }
@ -81,9 +85,11 @@ func (e Event) Item() (Item, error) {
} }
return Item{ return Item{
ID: e.ID, ID: e.ID,
Kind: KindEvent, Kind: KindEvent,
Body: string(body), Recurrer: e.Recurrer,
RecurNext: e.RecurNext,
Body: string(body),
}, nil }, nil
} }

View File

@ -18,11 +18,13 @@ var (
) )
type Item struct { type Item struct {
ID string `json:"id"` ID string `json:"id"`
Kind Kind `json:"kind"` Kind Kind `json:"kind"`
Updated time.Time `json:"updated"` Updated time.Time `json:"updated"`
Deleted bool `json:"deleted"` Deleted bool `json:"deleted"`
Body string `json:"body"` Recurrer *Recur `json:"recurrer"`
RecurNext time.Time `json:"recurNext"`
Body string `json:"body"`
} }
func NewItem(k Kind, body string) Item { func NewItem(k Kind, body string) Item {

View File

@ -10,9 +10,9 @@ const (
) )
type Recur struct { type Recur struct {
Start time.Time Start time.Time `json:"start"`
Period RecurPeriod Period RecurPeriod `json:"period"`
Count int Count int `json:"count"`
} }
func (r *Recur) On(date time.Time) bool { func (r *Recur) On(date time.Time) bool {

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"slices" "slices"
"sync" "sync"
"time" "time"
@ -44,3 +45,34 @@ func (m *Memory) Updated(kinds []item.Kind, timestamp time.Time) ([]item.Item, e
return result, nil return result, nil
} }
func (m *Memory) RecursBefore(date time.Time) ([]item.Item, error) {
res := make([]item.Item, 0)
for _, i := range m.items {
if i.Recurrer == nil {
continue
}
if i.RecurNext.Before(date) {
res = append(res, i)
}
}
return res, nil
}
func (m *Memory) RecursNext(id string, date time.Time) error {
i, ok := m.items[id]
if !ok {
return ErrNotFound
}
if i.Recurrer == nil {
return ErrNotARecurrer
}
if !i.Recurrer.On(date) {
return fmt.Errorf("item does not recur on %v", date)
}
i.RecurNext = date
i.Updated = time.Now()
m.items[id] = i
return nil
}

View File

@ -5,10 +5,11 @@ import (
"testing" "testing"
"time" "time"
"github.com/google/go-cmp/cmp"
"go-mod.ewintr.nl/planner/item" "go-mod.ewintr.nl/planner/item"
) )
func TestMemoryItem(t *testing.T) { func TestMemoryUpdate(t *testing.T) {
t.Parallel() t.Parallel()
mem := NewMemory() mem := NewMemory()
@ -109,3 +110,62 @@ func TestMemoryItem(t *testing.T) {
t.Errorf("exp %v, got %v", t1.ID, actItems[0].ID) t.Errorf("exp %v, got %v", t1.ID, actItems[0].ID)
} }
} }
func TestMemoryRecur(t *testing.T) {
t.Parallel()
mem := NewMemory()
now := time.Now()
earlier := now.Add(-5 * time.Minute)
today := time.Date(2024, 12, 1, 0, 0, 0, 0, time.UTC)
yesterday := time.Date(2024, 11, 30, 0, 0, 0, 0, time.UTC)
tomorrow := time.Date(2024, 12, 2, 0, 0, 0, 0, time.UTC)
t.Log("start")
i1 := item.Item{
ID: "a",
Updated: earlier,
Recurrer: &item.Recur{
Start: yesterday,
Period: item.PeriodDay,
Count: 1,
},
RecurNext: yesterday,
}
i2 := item.Item{
ID: "b",
Updated: earlier,
}
for _, i := range []item.Item{i1, i2} {
if err := mem.Update(i); err != nil {
t.Errorf("exp nil, ot %v", err)
}
}
t.Log("get recurrers")
rs, err := mem.RecursBefore(today)
if err != nil {
t.Errorf("exp nil, gt %v", err)
}
if diff := cmp.Diff([]item.Item{i1}, rs); diff != "" {
t.Errorf("(exp +, got -)\n%s", diff)
}
t.Log("set next")
if err := mem.RecursNext(i1.ID, tomorrow); err != nil {
t.Errorf("exp nil, got %v", err)
}
t.Log("check result")
us, err := mem.Updated([]item.Kind{}, now)
if err != nil {
t.Errorf("exp nil, got %v", err)
}
if len(us) != 1 {
t.Errorf("exp 1, got %v", len(us))
}
if us[0].ID != i1.ID {
t.Errorf("exp %v, got %v", i1.ID, us[0].ID)
}
}

View File

@ -8,10 +8,16 @@ import (
) )
var ( var (
ErrNotFound = errors.New("not found") ErrNotFound = errors.New("not found")
ErrNotARecurrer = errors.New("not a recurrer")
) )
type Syncer interface { type Syncer interface {
Update(item item.Item) error Update(item item.Item) error
Updated(kind []item.Kind, t time.Time) ([]item.Item, error) Updated(kind []item.Kind, t time.Time) ([]item.Item, error)
} }
type Recurrer interface {
RecursBefore(date time.Time) ([]item.Item, error)
RecursNext(id string, date time.Time) error
}