diff --git a/sm2.go b/sm2.go index 05fd1cf..fba3e67 100644 --- a/sm2.go +++ b/sm2.go @@ -1,9 +1,22 @@ package main -func SM2Next(thisGrade int, consecutivePassesBeforeThis int, ef float64, lastInterval int) (int, float64, int) { +import ( + "time" +) + +func Next(ts time.Time, history []int) time.Time { + n, ef, i := 0, 2.5, 1 + for j := range history { + n, ef, i = sm2Next(history[j], n, ef, i) + } + return ts.Add(time.Duration(i) * time.Hour * 24) +} + +// After all scheduled reviews are complete, SuperMemo asks the user to re-review any cards they marked with a grade less than 4 repeatedly until they give a grade ≥ 4. +func sm2Next(thisGrade int, consecutivePassesBeforeThis int, efBefore float64, lastInterval int) (int, float64, int) { q := thisGrade n := consecutivePassesBeforeThis - ef = ef + ef := efBefore i := lastInterval if q >= 3 { diff --git a/sm2_test.go b/sm2_test.go new file mode 100644 index 0000000..b66f645 --- /dev/null +++ b/sm2_test.go @@ -0,0 +1,54 @@ +package main + +import ( + "testing" + "time" +) + +func TestSM2(t *testing.T) { + ts := time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local) + cases := map[string]struct { + history []int + want int + }{ + "never before and no attempts": { + history: nil, + want: 1, + }, + "0": { + history: []int{3, 3, 3, 0}, + want: 1, + }, + "1": { + history: []int{3, 3, 0, 3}, + want: 1, + }, + "2": { + history: []int{3, 0, 3, 3}, + want: 6, + }, + "3": { + history: []int{0, 3, 3, 3}, + want: 8, + }, + "4": { + history: []int{3, 3, 3, 3}, + want: 27, + }, + "5": { + history: []int{3, 3, 3, 3, 3}, + want: 52, + }, + } + + for name, d := range cases { + c := d + t.Run(name, func(t *testing.T) { + got := Next(ts, c.history) + t.Logf("Next(\n\t%s, \n\t%+v) = \n\t%s", ts, c.history, got) + if got != ts.Add(time.Duration(c.want)*time.Hour*24) { + t.Error(c.want, got) + } + }) + } +}