diff options
| -rw-r--r-- | org-drill.el | 39 | ||||
| -rw-r--r-- | tests/test-org-drill-determine-next-interval-simple8.el | 70 | ||||
| -rw-r--r-- | tests/test-org-drill-prompt-and-format-helpers.el | 6 | ||||
| -rw-r--r-- | tests/testutil-scheduler.el | 10 |
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 |
