aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--org-drill.el39
-rw-r--r--tests/test-org-drill-determine-next-interval-simple8.el70
-rw-r--r--tests/test-org-drill-prompt-and-format-helpers.el6
-rw-r--r--tests/testutil-scheduler.el10
4 files changed, 64 insertions, 61 deletions
diff --git a/org-drill.el b/org-drill.el
index d772657..35d4192 100644
--- a/org-drill.el
+++ b/org-drill.el
@@ -1435,17 +1435,12 @@ to a mean item quality of QUALITY."
(* -1.2403 quality)
1.4515))
-(defun org-drill-determine-next-interval-simple8 (last-interval repeats quality
- failures meanq totaln
- &optional delta-days)
- "Arguments:
-- LAST-INTERVAL -- the number of days since the item was last reviewed.
-- REPEATS -- the number of times the item has been successfully reviewed
-- EASE -- the \\='easiness factor\\='
-- QUALITY -- 0 to 5
-- DELTA-DAYS -- how many days overdue was the item when it was reviewed.
- 0 = reviewed on the scheduled day. +N = N days overdue.
- -N = reviewed N days early.
+(defun org-drill-determine-next-interval-simple8 (state quality &optional delta-days)
+ "Return the Simple8 schedule for STATE after a review of recall QUALITY (0-5).
+
+STATE is an `org-drill-card-state'. DELTA-DAYS is how many days overdue
+the item was when reviewed: 0 = on the scheduled day, +N = N days late,
+-N = N days early.
Returns the new item data, as a list of 6 values:
- NEXT-INTERVAL
@@ -1455,6 +1450,11 @@ Returns the new item data, as a list of 6 values:
- AVERAGE-QUALITY
- TOTAL-REPEATS.
See the documentation for `org-drill-get-item-data' for a description of these."
+ (let ((last-interval (org-drill-card-state-last-interval state))
+ (repeats (org-drill-card-state-repetitions state))
+ (failures (org-drill-card-state-failures state))
+ (meanq (org-drill-card-state-meanq state))
+ (totaln (org-drill-card-state-total-repeats state)))
(cl-assert (>= repeats 0))
(cl-assert (and (>= quality 0) (<= quality 5)))
(cl-assert (or (null meanq) (and (>= meanq 0) (<= meanq 5))))
@@ -1503,7 +1503,7 @@ See the documentation for `org-drill-get-item-data' for a description of these."
failures
meanq
totaln
- )))
+ ))))
;;; Essentially copied from `org-learn.el', but modified to
;;; optionally call the SM2 or simple8 functions.
@@ -1529,13 +1529,7 @@ item will be scheduled exactly this many days into the future."
(sm5 (org-drill-determine-next-interval-sm5 state quality ofmatrix))
(sm2 (org-drill-determine-next-interval-sm2 state quality))
(simple8 (org-drill-determine-next-interval-simple8
- (org-drill-card-state-last-interval state)
- (org-drill-card-state-repetitions state)
- quality
- (org-drill-card-state-failures state)
- (org-drill-card-state-meanq state)
- (org-drill-card-state-total-repeats state)
- delta-days)))
+ state quality delta-days)))
(if (numberp days-ahead)
(setq next-interval days-ahead))
@@ -1587,12 +1581,7 @@ of QUALITY."
state quality org-drill-sm5-optimal-factor-matrix))
(sm2 (org-drill-determine-next-interval-sm2 state quality))
(simple8 (org-drill-determine-next-interval-simple8
- (org-drill-card-state-last-interval state)
- (org-drill-card-state-repetitions state)
- quality
- (org-drill-card-state-failures state)
- (org-drill-card-state-meanq state)
- (org-drill-card-state-total-repeats state))))
+ state quality)))
(cond
((not (cl-plusp next-interval))
0)
diff --git a/tests/test-org-drill-determine-next-interval-simple8.el b/tests/test-org-drill-determine-next-interval-simple8.el
index b3764cd..c2d1563 100644
--- a/tests/test-org-drill-determine-next-interval-simple8.el
+++ b/tests/test-org-drill-determine-next-interval-simple8.el
@@ -14,7 +14,7 @@
;; early-and-late-repetitions-p is enabled.
;;
;; Function signature:
-;; (org-drill-determine-next-interval-simple8 last-interval repeats quality
+;; (test-scheduler--call-simple8 last-interval repeats quality
;; failures meanq totaln
;; &optional delta-days)
;;
@@ -35,7 +35,7 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-first-review-quality-4 ()
"Normal: first review (repeats=0, last-interval=0) uses first-interval branch."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 0 0 4 0 nil 0 nil))
+ (let* ((result (test-scheduler--call-simple8 0 0 4 0 nil 0 nil))
(interval (test-scheduler--extract-interval result))
(repeats (test-scheduler--extract-repeats result)))
(should (> interval 0))
@@ -44,7 +44,7 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-second-review-quality-4 ()
"Normal: subsequent review uses interval-factor branch and grows the interval."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 nil))
+ (let* ((result (test-scheduler--call-simple8 4 1 4 0 nil 1 nil))
(interval (test-scheduler--extract-interval result))
(repeats (test-scheduler--extract-repeats result)))
(should (> interval 0))
@@ -53,7 +53,7 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-third-review-quality-4 ()
"Normal: third review continues the interval-factor branch."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 10 2 4 0 4.0 2 nil))
+ (let* ((result (test-scheduler--call-simple8 10 2 4 0 4.0 2 nil))
(interval (test-scheduler--extract-interval result))
(repeats (test-scheduler--extract-repeats result)))
(should (> interval 0))
@@ -62,8 +62,8 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-quality-5-perfect-recall ()
"Normal: quality 5 produces a higher ease than the same call with quality 3."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result-q5 (org-drill-determine-next-interval-simple8 10 2 5 0 5.0 2 nil))
- (result-q3 (org-drill-determine-next-interval-simple8 10 2 3 0 3.0 2 nil))
+ (let* ((result-q5 (test-scheduler--call-simple8 10 2 5 0 5.0 2 nil))
+ (result-q3 (test-scheduler--call-simple8 10 2 3 0 3.0 2 nil))
(ease-q5 (test-scheduler--extract-ease result-q5))
(ease-q3 (test-scheduler--extract-ease result-q3)))
(should (> ease-q5 ease-q3)))))
@@ -71,13 +71,13 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-quality-3-adequate-recall ()
"Normal: quality 3 passes (above failure threshold) and increments repeats."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 10 2 3 0 3.0 2 nil))
+ (let* ((result (test-scheduler--call-simple8 10 2 3 0 3.0 2 nil))
(repeats (test-scheduler--extract-repeats result)))
(should (= repeats 3)))))
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-failure-quality-0 ()
"Normal: failed review with quality 0 resets interval to -1 and repeats to 0."
- (let* ((result (org-drill-determine-next-interval-simple8 10 3 0 0 nil 3 nil))
+ (let* ((result (test-scheduler--call-simple8 10 3 0 0 nil 3 nil))
(interval (test-scheduler--extract-interval result))
(repeats (test-scheduler--extract-repeats result))
(failures (test-scheduler--extract-failures result)))
@@ -87,7 +87,7 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-failure-quality-1 ()
"Normal: failed review with quality 1 resets interval and increments failures."
- (let* ((result (org-drill-determine-next-interval-simple8 15 5 1 2 3.5 5 nil))
+ (let* ((result (test-scheduler--call-simple8 15 5 1 2 3.5 5 nil))
(interval (test-scheduler--extract-interval result))
(failures (test-scheduler--extract-failures result)))
(should (= interval -1))
@@ -95,7 +95,7 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-normal-failure-quality-2 ()
"Normal: quality 2 (= default org-drill-failure-quality) triggers failure path."
- (let* ((result (org-drill-determine-next-interval-simple8 10 3 2 0 nil 3 nil))
+ (let* ((result (test-scheduler--call-simple8 10 3 2 0 nil 3 nil))
(interval (test-scheduler--extract-interval result)))
(should (= interval -1))))
@@ -104,14 +104,14 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-boundary-nil-meanq-uses-quality ()
"Boundary: nil meanq initializes to current quality."
(let* ((quality 4)
- (result (org-drill-determine-next-interval-simple8 0 0 quality 0 nil 0 nil))
+ (result (test-scheduler--call-simple8 0 0 quality 0 nil 0 nil))
(meanq (test-scheduler--extract-meanq result)))
(should (= meanq quality))))
(ert-deftest test-org-drill-determine-next-interval-simple8-boundary-zero-repeats-forces-first-interval ()
"Boundary: zero repeats forces first-interval branch (last-interval > 0)."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 100 0 4 0 nil 0 nil))
+ (let* ((result (test-scheduler--call-simple8 100 0 4 0 nil 0 nil))
(interval (test-scheduler--extract-interval result)))
;; First-interval is small (around 2.4849), not last-interval * factor.
(should (> interval 0))
@@ -120,20 +120,20 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-boundary-zero-last-interval-forces-first-interval ()
"Boundary: zero last-interval forces first-interval branch (repeats > 0)."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 0 5 4 0 4.0 5 nil))
+ (let* ((result (test-scheduler--call-simple8 0 5 4 0 4.0 5 nil))
(interval (test-scheduler--extract-interval result)))
(should (> interval 0)))))
(ert-deftest test-org-drill-determine-next-interval-simple8-boundary-quality-5-maximum ()
"Boundary: maximum quality 5 is accepted and produces a positive interval."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 4 1 5 0 nil 1 nil))
+ (let* ((result (test-scheduler--call-simple8 4 1 5 0 nil 1 nil))
(interval (test-scheduler--extract-interval result)))
(should (> interval 0)))))
(ert-deftest test-org-drill-determine-next-interval-simple8-boundary-quality-0-minimum ()
"Boundary: minimum quality 0 triggers the failure path with interval -1."
- (let* ((result (org-drill-determine-next-interval-simple8 10 3 0 0 nil 3 nil))
+ (let* ((result (test-scheduler--call-simple8 10 3 0 0 nil 3 nil))
(interval (test-scheduler--extract-interval result)))
(should (= interval -1))))
@@ -142,7 +142,7 @@
(let* ((quality 4)
(meanq 3.0)
(totaln 10)
- (result (org-drill-determine-next-interval-simple8 10 3 quality 0 meanq totaln nil))
+ (result (test-scheduler--call-simple8 10 3 quality 0 meanq totaln nil))
(new-meanq (test-scheduler--extract-meanq result))
(expected (/ (+ quality (* meanq totaln 1.0)) (1+ totaln))))
(should (< (abs (- new-meanq expected)) 0.0001))))
@@ -150,7 +150,7 @@
(ert-deftest test-org-drill-determine-next-interval-simple8-boundary-delta-days-nil ()
"Boundary: nil delta-days (default) skips both early and late adjustments."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 nil))
+ (let* ((result (test-scheduler--call-simple8 4 1 4 0 nil 1 nil))
(interval (test-scheduler--extract-interval result)))
(should (numberp interval))
(should (> interval 0)))))
@@ -159,8 +159,8 @@
"Boundary: positive delta-days with flag disabled does not change the interval."
(let ((org-drill-add-random-noise-to-intervals-p nil)
(org-drill-adjust-intervals-for-early-and-late-repetitions-p nil))
- (let* ((result-no-adjust (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 5))
- (result-no-delta (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 nil))
+ (let* ((result-no-adjust (test-scheduler--call-simple8 4 1 4 0 nil 1 5))
+ (result-no-delta (test-scheduler--call-simple8 4 1 4 0 nil 1 nil))
(interval-no-adjust (test-scheduler--extract-interval result-no-adjust))
(interval-no-delta (test-scheduler--extract-interval result-no-delta)))
(should (= interval-no-adjust interval-no-delta)))))
@@ -169,7 +169,7 @@
"Boundary: positive delta-days with flag enabled runs late-review adjustment."
(let ((org-drill-add-random-noise-to-intervals-p nil)
(org-drill-adjust-intervals-for-early-and-late-repetitions-p t))
- (let* ((result (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 5))
+ (let* ((result (test-scheduler--call-simple8 4 1 4 0 nil 1 5))
(interval (test-scheduler--extract-interval result)))
(should (numberp interval))
(should (> interval 0)))))
@@ -178,8 +178,8 @@
"Boundary: negative delta-days with flag disabled does not change the interval."
(let ((org-drill-add-random-noise-to-intervals-p nil)
(org-drill-adjust-intervals-for-early-and-late-repetitions-p nil))
- (let* ((result-no-adjust (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 -3))
- (result-no-delta (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 nil))
+ (let* ((result-no-adjust (test-scheduler--call-simple8 4 1 4 0 nil 1 -3))
+ (result-no-delta (test-scheduler--call-simple8 4 1 4 0 nil 1 nil))
(interval-no-adjust (test-scheduler--extract-interval result-no-adjust))
(interval-no-delta (test-scheduler--extract-interval result-no-delta)))
(should (= interval-no-adjust interval-no-delta)))))
@@ -188,7 +188,7 @@
"Boundary: negative delta-days with flag enabled runs early-interval-factor."
(let ((org-drill-add-random-noise-to-intervals-p nil)
(org-drill-adjust-intervals-for-early-and-late-repetitions-p t))
- (let* ((result (org-drill-determine-next-interval-simple8 4 1 4 0 nil 1 -3))
+ (let* ((result (test-scheduler--call-simple8 4 1 4 0 nil 1 -3))
(interval (test-scheduler--extract-interval result)))
(should (numberp interval))
(should (> interval 0)))))
@@ -198,8 +198,8 @@
This matches the SM2 and SM5 behavior so DRILL_TOTAL_REPEATS counts every
review attempt regardless of which scheduling algorithm produced it."
(let* ((totaln 42)
- (result-success (org-drill-determine-next-interval-simple8 0 0 4 0 nil totaln nil))
- (result-failure (org-drill-determine-next-interval-simple8 10 3 0 0 nil totaln nil)))
+ (result-success (test-scheduler--call-simple8 0 0 4 0 nil totaln nil))
+ (result-failure (test-scheduler--call-simple8 10 3 0 0 nil totaln nil)))
(should (= (test-scheduler--extract-total-repeats result-success) (1+ totaln)))
(should (= (test-scheduler--extract-total-repeats result-failure) (1+ totaln)))))
@@ -228,33 +228,33 @@ where ERT's hook leaves inner condition-case alone."
(ert-deftest test-org-drill-determine-next-interval-simple8-error-negative-repeats ()
"Error: repeats=-1 violates the (cl-assert (>= repeats 0)) precondition."
(test-scheduler--should-cl-assert
- (org-drill-determine-next-interval-simple8 0 -1 4 0 nil 0 nil)))
+ (test-scheduler--call-simple8 0 -1 4 0 nil 0 nil)))
(ert-deftest test-org-drill-determine-next-interval-simple8-error-quality-below-zero ()
"Error: quality=-1 violates the cl-assert quality range."
(test-scheduler--should-cl-assert
- (org-drill-determine-next-interval-simple8 0 0 -1 0 nil 0 nil)))
+ (test-scheduler--call-simple8 0 0 -1 0 nil 0 nil)))
(ert-deftest test-org-drill-determine-next-interval-simple8-error-quality-above-five ()
"Error: quality=6 violates the cl-assert quality range."
(test-scheduler--should-cl-assert
- (org-drill-determine-next-interval-simple8 0 0 6 0 nil 0 nil)))
+ (test-scheduler--call-simple8 0 0 6 0 nil 0 nil)))
(ert-deftest test-org-drill-determine-next-interval-simple8-error-meanq-above-five ()
"Error: meanq=10 violates the meanq cl-assert (Simple8-specific check)."
(test-scheduler--should-cl-assert
- (org-drill-determine-next-interval-simple8 10 3 4 0 10.0 3 nil)))
+ (test-scheduler--call-simple8 10 3 4 0 10.0 3 nil)))
(ert-deftest test-org-drill-determine-next-interval-simple8-error-meanq-below-zero ()
"Error: meanq=-1 violates the meanq cl-assert (Simple8-specific check)."
(test-scheduler--should-cl-assert
- (org-drill-determine-next-interval-simple8 10 3 4 0 -1.0 3 nil)))
+ (test-scheduler--call-simple8 10 3 4 0 -1.0 3 nil)))
;;; Algorithm Verification
(ert-deftest test-org-drill-determine-next-interval-simple8-algorithm-return-value-structure ()
"Algorithm: return value is a 6-element list (not 7 like SM2/SM5)."
- (let ((result (org-drill-determine-next-interval-simple8 10 3 4 0 3.5 10 nil)))
+ (let ((result (test-scheduler--call-simple8 10 3 4 0 3.5 10 nil)))
(should (listp result))
(should (= (length result) 6))
(should (numberp (nth 0 result))) ; interval
@@ -266,13 +266,13 @@ where ERT's hook leaves inner condition-case alone."
(ert-deftest test-org-drill-determine-next-interval-simple8-algorithm-failure-resets-repeats-to-zero ()
"Algorithm: failure path resets repeats to 0, regardless of input value."
- (let* ((result (org-drill-determine-next-interval-simple8 10 7 0 0 nil 7 nil))
+ (let* ((result (test-scheduler--call-simple8 10 7 0 0 nil 7 nil))
(repeats (test-scheduler--extract-repeats result)))
(should (= repeats 0))))
(ert-deftest test-org-drill-determine-next-interval-simple8-algorithm-ease-derived-from-meanq ()
"Algorithm: returned ease = simple8-quality->ease(returned-meanq)."
- (let* ((result (org-drill-determine-next-interval-simple8 10 2 4 0 4.0 2 nil))
+ (let* ((result (test-scheduler--call-simple8 10 2 4 0 4.0 2 nil))
(returned-ease (test-scheduler--extract-ease result))
(returned-meanq (test-scheduler--extract-meanq result))
(expected-ease (org-drill-simple8-quality->ease returned-meanq)))
@@ -281,10 +281,10 @@ where ERT's hook leaves inner condition-case alone."
(ert-deftest test-org-drill-determine-next-interval-simple8-algorithm-interval-grows-over-successive-reviews ()
"Algorithm: successive successful quality-4 reviews produce growing intervals."
(let ((org-drill-add-random-noise-to-intervals-p nil))
- (let* ((result-1 (org-drill-determine-next-interval-simple8 0 0 4 0 nil 0 nil))
+ (let* ((result-1 (test-scheduler--call-simple8 0 0 4 0 nil 0 nil))
(interval-1 (test-scheduler--extract-interval result-1))
(meanq-1 (test-scheduler--extract-meanq result-1))
- (result-2 (org-drill-determine-next-interval-simple8 interval-1 1 4 0 meanq-1 1 nil))
+ (result-2 (test-scheduler--call-simple8 interval-1 1 4 0 meanq-1 1 nil))
(interval-2 (test-scheduler--extract-interval result-2)))
(should (> interval-2 interval-1)))))
diff --git a/tests/test-org-drill-prompt-and-format-helpers.el b/tests/test-org-drill-prompt-and-format-helpers.el
index 3bd3e5a..91e076c 100644
--- a/tests/test-org-drill-prompt-and-format-helpers.el
+++ b/tests/test-org-drill-prompt-and-format-helpers.el
@@ -105,7 +105,11 @@ next-interval is multiplied by a small dispersal factor (≠1.0 in general)."
(cl-letf (((symbol-function 'org-drill-random-dispersal-factor)
(lambda () 1.5)))
(let* ((result (org-drill-determine-next-interval-simple8
- 4.0 1 5 0 5.0 1 0))
+ (make-org-drill-card-state
+ :last-interval 4.0 :repetitions 1
+ :failures 0 :meanq 5.0 :total-repeats 1)
+ 5
+ 0))
(next (nth 0 result)))
;; With factor 1.5, the original next-interval was scaled up.
(should (numberp next))
diff --git a/tests/testutil-scheduler.el b/tests/testutil-scheduler.el
index 0d28b7a..126e6e8 100644
--- a/tests/testutil-scheduler.el
+++ b/tests/testutil-scheduler.el
@@ -66,5 +66,15 @@ Use this name in Simple8 tests where the field is called `ease' not `ef'."
:failures failures :meanq meanq :total-repeats total-repeats)
quality of-matrix delta-days))
+(defun test-scheduler--call-simple8 (last-interval repeats quality failures
+ meanq totaln &optional delta-days)
+ "Call the Simple8 scheduler from positional args, packing them into a card-state.
+Simple8 doesn't use the ease slot; it's left unset in the struct."
+ (org-drill-determine-next-interval-simple8
+ (make-org-drill-card-state
+ :last-interval last-interval :repetitions repeats
+ :failures failures :meanq meanq :total-repeats totaln)
+ quality delta-days))
+
(provide 'testutil-scheduler)
;;; testutil-scheduler.el ends here