diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-27 21:28:20 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-27 21:28:20 -0500 |
| commit | 6e3f2d278d9598c6838428ee510445f51888bb30 (patch) | |
| tree | 98ca78149861191d32012a4148b1ce239cf08a75 | |
| parent | eaa0a53f807b44d8a4bf72f3de562b011f69756e (diff) | |
| download | org-drill-6e3f2d278d9598c6838428ee510445f51888bb30.tar.gz org-drill-6e3f2d278d9598c6838428ee510445f51888bb30.zip | |
refactor: take card-state in org-drill-determine-next-interval-sm2
Stage 3 of #147. sm2 now takes (state quality) instead of seven positional args, binding the recall fields from the struct at the top so the algorithm body is unchanged. The smart-reschedule and hypothetical-next-review-date call sites pass the state they already hold, which drops the per-branch accessor unpacking.
I kept the return as the existing positional list rather than restructuring it too. The goal is reducing the input signature, and changing the return shape would force the shared test extractors and every return-read to change for no real gain. A testutil adapter, test-scheduler--call-sm2, packs positional args into the struct, so the test call sites stay readable as the documented algorithm inputs and the migration is a one-symbol rename per call.
| -rw-r--r-- | org-drill.el | 37 | ||||
| -rw-r--r-- | tests/test-org-drill-determine-next-interval-sm2.el | 92 | ||||
| -rw-r--r-- | tests/testutil-scheduler.el | 14 |
3 files changed, 75 insertions, 68 deletions
diff --git a/org-drill.el b/org-drill.el index fd6f24e..7046ade 100644 --- a/org-drill.el +++ b/org-drill.el @@ -1232,13 +1232,12 @@ caller passes the scheduler's next-interval there)." (org-drill-round-float (org-drill-card-state-ease state) 3)))) ;;; SM2 Algorithm ============================================================= -(defun org-drill-determine-next-interval-sm2 (last-interval n ef quality - failures meanq total-repeats) - "Arguments: -- LAST-INTERVAL -- the number of days since the item was last reviewed. -- REPEATS -- the number of times the item has been successfully reviewed -- EF -- the \\='easiness factor\\=' -- QUALITY -- 0 to 5 +(defun org-drill-determine-next-interval-sm2 (state quality) + "Return the SM2 schedule for STATE after a review of recall QUALITY (0-5). + +STATE is an `org-drill-card-state' carrying LAST-INTERVAL, REPETITIONS, +EASE (the \\='easiness factor\\='), FAILURES, MEANQ and TOTAL-REPEATS. +QUALITY is the rating just entered. Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), where: @@ -1246,6 +1245,12 @@ Returns a list: - REPEATS is incremented by 1. - EF is modified based on the recall quality for the item. - OF-MATRIX is not modified." + (let ((last-interval (org-drill-card-state-last-interval state)) + (n (org-drill-card-state-repetitions state)) + (ef (org-drill-card-state-ease state)) + (failures (org-drill-card-state-failures state)) + (meanq (org-drill-card-state-meanq state)) + (total-repeats (org-drill-card-state-total-repeats state))) (if (zerop n) (setq n 1)) (if (null ef) (setq ef 2.5)) (setq meanq (if meanq @@ -1282,7 +1287,7 @@ Returns a list: (1+ n) next-ef failures meanq (1+ total-repeats) - org-drill-sm5-optimal-factor-matrix)))) + org-drill-sm5-optimal-factor-matrix))))) ;;; SM5 Algorithm ============================================================= (defun org-drill-modify-e-factor (ef quality) @@ -1520,13 +1525,7 @@ item will be scheduled exactly this many days into the future." (org-drill-card-state-failures state) (org-drill-card-state-meanq state) (org-drill-card-state-total-repeats state) ofmatrix)) - (sm2 (org-drill-determine-next-interval-sm2 - (org-drill-card-state-last-interval state) - (org-drill-card-state-repetitions state) - (org-drill-card-state-ease state) quality - (org-drill-card-state-failures state) - (org-drill-card-state-meanq state) - (org-drill-card-state-total-repeats state))) + (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) @@ -1590,13 +1589,7 @@ of QUALITY." (org-drill-card-state-meanq state) (org-drill-card-state-total-repeats state) org-drill-sm5-optimal-factor-matrix)) - (sm2 (org-drill-determine-next-interval-sm2 - (org-drill-card-state-last-interval state) - (org-drill-card-state-repetitions state) - (org-drill-card-state-ease state) quality - (org-drill-card-state-failures state) - (org-drill-card-state-meanq state) - (org-drill-card-state-total-repeats state))) + (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) diff --git a/tests/test-org-drill-determine-next-interval-sm2.el b/tests/test-org-drill-determine-next-interval-sm2.el index 8405968..b367f33 100644 --- a/tests/test-org-drill-determine-next-interval-sm2.el +++ b/tests/test-org-drill-determine-next-interval-sm2.el @@ -12,7 +12,7 @@ ;; - Failure count and statistics ;; ;; Function signature: -;; (org-drill-determine-next-interval-sm2 last-interval n ef quality +;; (test-scheduler--call-sm2 last-interval n ef quality ;; failures meanq total-repeats) ;; ;; Returns: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX) @@ -41,7 +41,7 @@ (ert-deftest test-org-drill-determine-next-interval-sm2-normal-first-review-quality-4 () "Test first successful review with quality 4. First review (n=1) should return interval of 1 day." - (let* ((result (org-drill-determine-next-interval-sm2 0 1 nil 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 0 1 nil 4 0 nil 0)) (interval (test-scheduler--extract-interval result)) (repeats (test-scheduler--extract-repeats result)) (ef (test-scheduler--extract-ef result))) @@ -53,7 +53,7 @@ First review (n=1) should return interval of 1 day." "Test second successful review with quality 4. Second review (n=2) should return interval of 6 days (no random noise)." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 1 2 2.5 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 1 2 2.5 4 0 nil 0)) (interval (test-scheduler--extract-interval result)) (repeats (test-scheduler--extract-repeats result))) (should (= interval 6)) @@ -65,7 +65,7 @@ Third review (n=3) uses formula: last-interval * EF." (let ((org-drill-add-random-noise-to-intervals-p nil)) (let* ((ef 2.5) (last-interval 6) - (result (org-drill-determine-next-interval-sm2 last-interval 3 ef 4 0 nil 0)) + (result (test-scheduler--call-sm2 last-interval 3 ef 4 0 nil 0)) (interval (test-scheduler--extract-interval result)) (new-ef (test-scheduler--extract-ef result))) ;; Interval should be approximately last-interval * new-ef @@ -76,7 +76,7 @@ Third review (n=3) uses formula: last-interval * EF." "Test review with perfect recall (quality 5). Quality 5 should increase EF and result in longer intervals." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 5 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 5 0 nil 0)) (ef (test-scheduler--extract-ef result))) ;; Quality 5 should maintain or increase EF (should (>= ef 2.5))))) @@ -85,7 +85,7 @@ Quality 5 should increase EF and result in longer intervals." "Test review with adequate recall (quality 3). Quality 3 should maintain relatively stable EF." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 3 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 3 0 nil 0)) (ef (test-scheduler--extract-ef result))) ;; Quality 3 should result in moderate EF (should (> ef test-sm2-min-ef)) @@ -96,7 +96,7 @@ Quality 3 should maintain relatively stable EF." (ert-deftest test-org-drill-determine-next-interval-sm2-normal-failure-quality-0 () "Test failed review with quality 0. Quality 0 (<= org-drill-failure-quality) should reset interval to -1." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 0 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 0 0 nil 0)) (interval (test-scheduler--extract-interval result)) (repeats (test-scheduler--extract-repeats result)) (ef (test-scheduler--extract-ef result)) @@ -109,7 +109,7 @@ Quality 0 (<= org-drill-failure-quality) should reset interval to -1." (ert-deftest test-org-drill-determine-next-interval-sm2-normal-failure-quality-1 () "Test failed review with quality 1. Quality 1 (<= org-drill-failure-quality) should reset interval." - (let* ((result (org-drill-determine-next-interval-sm2 15 5 2.6 1 2 3.5 10)) + (let* ((result (test-scheduler--call-sm2 15 5 2.6 1 2 3.5 10)) (interval (test-scheduler--extract-interval result)) (ef (test-scheduler--extract-ef result)) (failures (test-scheduler--extract-failures result))) @@ -120,7 +120,7 @@ Quality 1 (<= org-drill-failure-quality) should reset interval." (ert-deftest test-org-drill-determine-next-interval-sm2-normal-failure-quality-2 () "Test failed review with quality 2. Quality 2 (= org-drill-failure-quality default) should reset interval." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 2 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 2 0 nil 0)) (interval (test-scheduler--extract-interval result))) (should (= interval -1)))) @@ -128,14 +128,14 @@ Quality 2 (= org-drill-failure-quality default) should reset interval." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-nil-ef-uses-default () "Test that nil EF defaults to 2.5." - (let* ((result (org-drill-determine-next-interval-sm2 0 1 nil 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 0 1 nil 4 0 nil 0)) (ef (test-scheduler--extract-ef result))) (should ef) ; EF should be set (modified from default 2.5) (should (> ef 0)))) (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-zero-n-becomes-one () "Test that n=0 is treated as n=1." - (let* ((result (org-drill-determine-next-interval-sm2 0 0 2.5 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 0 0 2.5 4 0 nil 0)) (interval (test-scheduler--extract-interval result)) (repeats (test-scheduler--extract-repeats result))) (should (= interval 1)) ; First review interval @@ -144,7 +144,7 @@ Quality 2 (= org-drill-failure-quality default) should reset interval." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-nil-meanq-uses-quality () "Test that nil meanq initializes to current quality." (let* ((quality 4) - (result (org-drill-determine-next-interval-sm2 0 1 2.5 quality 0 nil 0)) + (result (test-scheduler--call-sm2 0 1 2.5 quality 0 nil 0)) (meanq (test-scheduler--extract-meanq result))) (should (= meanq quality)))) @@ -153,13 +153,13 @@ Quality 2 (= org-drill-failure-quality default) should reset interval." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-quality-5-maximum () "Test maximum quality (5) - perfect recall." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 1 2 2.5 5 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 1 2 2.5 5 0 nil 0)) (interval (test-scheduler--extract-interval result))) (should (= interval 6))))) ; Second review with quality 5 (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-quality-0-minimum () "Test minimum quality (0) - complete failure." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 0 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 0 0 nil 0)) (interval (test-scheduler--extract-interval result))) (should (= interval -1)))) ; Failed review @@ -167,7 +167,7 @@ Quality 2 (= org-drill-failure-quality default) should reset interval." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-n-equals-1 () "Test first successful review (n=1) returns interval of 1." - (let* ((result (org-drill-determine-next-interval-sm2 0 1 2.5 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 0 1 2.5 4 0 nil 0)) (interval (test-scheduler--extract-interval result))) (should (= interval 1)))) @@ -175,7 +175,7 @@ Quality 2 (= org-drill-failure-quality default) should reset interval." "Test second review (n=2) with no random noise. Should return interval of 6 days regardless of quality (if passing)." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 1 2 2.5 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 1 2 2.5 4 0 nil 0)) (interval (test-scheduler--extract-interval result))) (should (= interval 6))))) @@ -183,9 +183,9 @@ Should return interval of 6 days regardless of quality (if passing)." "Test second review (n=2) with random noise enabled. Interval should vary by quality, with quality 5 having highest base interval (6)." (let ((org-drill-add-random-noise-to-intervals-p t)) - (let* ((result-q5 (org-drill-determine-next-interval-sm2 1 2 2.5 5 0 nil 0)) - (result-q4 (org-drill-determine-next-interval-sm2 1 2 2.5 4 0 nil 0)) - (result-q3 (org-drill-determine-next-interval-sm2 1 2 2.5 3 0 nil 0)) + (let* ((result-q5 (test-scheduler--call-sm2 1 2 2.5 5 0 nil 0)) + (result-q4 (test-scheduler--call-sm2 1 2 2.5 4 0 nil 0)) + (result-q3 (test-scheduler--call-sm2 1 2 2.5 3 0 nil 0)) (interval-q5 (test-scheduler--extract-interval result-q5)) (interval-q4 (test-scheduler--extract-interval result-q4)) (interval-q3 (test-scheduler--extract-interval result-q3))) @@ -206,7 +206,7 @@ meanq = (quality + meanq * total-repeats) / (total-repeats + 1)" (let* ((quality 4) (meanq 3.0) (total-repeats 10) - (result (org-drill-determine-next-interval-sm2 10 3 2.5 quality 0 meanq total-repeats)) + (result (test-scheduler--call-sm2 10 3 2.5 quality 0 meanq total-repeats)) (new-meanq (test-scheduler--extract-meanq result)) (expected-meanq (/ (+ quality (* meanq total-repeats 1.0)) (1+ total-repeats)))) @@ -217,7 +217,7 @@ meanq = (quality + meanq * total-repeats) / (total-repeats + 1)" (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-ef-minimum-floor () "Test that EF floor of 1.3 is applied to input EF when it's below 1.3. If input EF < 1.3, org-drill-modify-e-factor returns 1.3 exactly." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 1.0 4 0 nil 0)) + (let* ((result (test-scheduler--call-sm2 10 3 1.0 4 0 nil 0)) (ef (test-scheduler--extract-ef result))) ;; Input EF was 1.0 < 1.3, so it should be raised to 1.3 first, ;; then modified based on quality 4 (which increases EF) @@ -228,7 +228,7 @@ If input EF < 1.3, org-drill-modify-e-factor returns 1.3 exactly." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-total-repeats-increments () "Test that total-repeats is always incremented by 1." (let* ((total-repeats 42) - (result (org-drill-determine-next-interval-sm2 10 3 2.5 4 0 3.5 total-repeats)) + (result (test-scheduler--call-sm2 10 3 2.5 4 0 3.5 total-repeats)) (new-total (test-scheduler--extract-total-repeats result))) (should (= new-total (1+ total-repeats))))) @@ -237,7 +237,7 @@ If input EF < 1.3, org-drill-modify-e-factor returns 1.3 exactly." (ert-deftest test-org-drill-determine-next-interval-sm2-normal-return-value-structure () "Test that return value has correct structure. Should return 7-element list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX)" - (let ((result (org-drill-determine-next-interval-sm2 10 3 2.5 4 0 3.5 10))) + (let ((result (test-scheduler--call-sm2 10 3 2.5 4 0 3.5 10))) (should (listp result)) (should (= (length result) 7)) ;; Verify first 6 elements are numbers @@ -257,7 +257,7 @@ Should return 7-element list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS O "Test that higher quality results in higher EF (or maintains it). Quality 5 should result in EF >= initial EF." (let* ((initial-ef 2.5) - (result (org-drill-determine-next-interval-sm2 10 3 initial-ef 5 0 nil 0)) + (result (test-scheduler--call-sm2 10 3 initial-ef 5 0 nil 0)) (new-ef (test-scheduler--extract-ef result))) (should (>= new-ef initial-ef)))) @@ -265,7 +265,7 @@ Quality 5 should result in EF >= initial EF." "Test that low quality results in decreased EF. Quality 3 should result in EF < initial EF." (let* ((initial-ef 2.5) - (result (org-drill-determine-next-interval-sm2 10 3 initial-ef 3 0 nil 0)) + (result (test-scheduler--call-sm2 10 3 initial-ef 3 0 nil 0)) (new-ef (test-scheduler--extract-ef result))) (should (< new-ef initial-ef)))) @@ -274,10 +274,10 @@ Quality 3 should result in EF < initial EF." Third review interval should be significantly larger than second." (let ((org-drill-add-random-noise-to-intervals-p nil)) (let* ((ef 2.5) - (result-2nd (org-drill-determine-next-interval-sm2 1 2 ef 4 0 nil 0)) + (result-2nd (test-scheduler--call-sm2 1 2 ef 4 0 nil 0)) (interval-2nd (test-scheduler--extract-interval result-2nd)) (ef-2nd (test-scheduler--extract-ef result-2nd)) - (result-3rd (org-drill-determine-next-interval-sm2 interval-2nd 3 ef-2nd 4 0 nil 1)) + (result-3rd (test-scheduler--call-sm2 interval-2nd 3 ef-2nd 4 0 nil 1)) (interval-3rd (test-scheduler--extract-interval result-3rd))) (should (> interval-3rd (* interval-2nd 1.5)))))) ; Significant growth @@ -287,7 +287,7 @@ Third review interval should be significantly larger than second." "Test SM2 with very high repeat count (1000 reviews). Algorithm should remain stable with extreme n values." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 365 1000 2.5 4 0 4.0 1000)) + (let* ((result (test-scheduler--call-sm2 365 1000 2.5 4 0 4.0 1000)) (interval (test-scheduler--extract-interval result)) (repeats (test-scheduler--extract-repeats result)) (ef (test-scheduler--extract-ef result))) @@ -300,7 +300,7 @@ Algorithm should remain stable with extreme n values." "Test SM2 with very long last interval (10 years = 3650 days). Algorithm should handle extreme intervals without overflow." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result (org-drill-determine-next-interval-sm2 3650 100 2.5 4 0 4.0 100)) + (let* ((result (test-scheduler--call-sm2 3650 100 2.5 4 0 4.0 100)) (interval (test-scheduler--extract-interval result))) (should (numberp interval)) (should (> interval 0))))) @@ -309,7 +309,7 @@ Algorithm should handle extreme intervals without overflow." "Test SM2 with very high failure count (100+ failures). Failure count should be tracked correctly even at extreme values." (let* ((failures 100) - (result (org-drill-determine-next-interval-sm2 10 3 2.5 0 failures 3.0 150)) + (result (test-scheduler--call-sm2 10 3 2.5 0 failures 3.0 150)) (new-failures (test-scheduler--extract-failures result))) (should (= new-failures (1+ failures))))) @@ -317,21 +317,21 @@ Failure count should be tracked correctly even at extreme values." "Test SM2 with very high total-repeats (10000+). Total repeats should increment correctly even at extreme values." (let* ((total-repeats 10000) - (result (org-drill-determine-next-interval-sm2 10 3 2.5 4 0 4.0 total-repeats)) + (result (test-scheduler--call-sm2 10 3 2.5 4 0 4.0 total-repeats)) (new-total (test-scheduler--extract-total-repeats result))) (should (= new-total (1+ total-repeats))))) (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-ef-just-above-floor () "Test SM2 with EF just above minimum floor (1.31). EF should be maintained or modified normally, not clamped." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 1.31 4 0 4.0 10)) + (let* ((result (test-scheduler--call-sm2 10 3 1.31 4 0 4.0 10)) (ef (test-scheduler--extract-ef result))) (should (>= ef test-sm2-min-ef)))) (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-ef-at-floor () "Test SM2 with EF exactly at minimum floor (1.3). EF at floor with quality 4 should increase slightly." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 1.3 4 0 4.0 10)) + (let* ((result (test-scheduler--call-sm2 10 3 1.3 4 0 4.0 10)) (ef (test-scheduler--extract-ef result))) (should (>= ef test-sm2-min-ef)))) @@ -340,7 +340,7 @@ EF at floor with quality 4 should increase slightly." Perfect recall should not reset failures, but should calculate normal interval." (let ((org-drill-add-random-noise-to-intervals-p nil)) (let* ((failures 50) - (result (org-drill-determine-next-interval-sm2 10 3 2.5 5 failures 3.0 100)) + (result (test-scheduler--call-sm2 10 3 2.5 5 failures 3.0 100)) (interval (test-scheduler--extract-interval result)) (new-failures (test-scheduler--extract-failures result))) (should (> interval 0)) @@ -349,7 +349,7 @@ Perfect recall should not reset failures, but should calculate normal interval." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-failure-after-long-streak () "Test complete failure (quality 0) after long successful streak. Failure should reset interval to -1 regardless of previous success." - (let* ((result (org-drill-determine-next-interval-sm2 365 100 2.8 0 0 4.5 100)) + (let* ((result (test-scheduler--call-sm2 365 100 2.8 0 0 4.5 100)) (interval (test-scheduler--extract-interval result)) (repeats (test-scheduler--extract-repeats result)) (failures (test-scheduler--extract-failures result))) @@ -360,7 +360,7 @@ Failure should reset interval to -1 regardless of previous success." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-meanq-at-maximum () "Test SM2 with meanq at maximum (5.0). High quality review with already-perfect meanq." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 5 0 5.0 100)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 5 0 5.0 100)) (meanq (test-scheduler--extract-meanq result))) (should (<= meanq 5.0)) (should (>= meanq 4.5)))) ; Should remain very high @@ -368,7 +368,7 @@ High quality review with already-perfect meanq." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-meanq-at-minimum () "Test SM2 with meanq at minimum (0.0). Low quality history with poor current recall." - (let* ((result (org-drill-determine-next-interval-sm2 10 3 2.5 3 5 0.0 100)) + (let* ((result (test-scheduler--call-sm2 10 3 2.5 3 5 0.0 100)) (meanq (test-scheduler--extract-meanq result))) (should (>= meanq 0.0)) (should (<= meanq 1.0)))) ; Should remain low with quality 3 @@ -378,7 +378,7 @@ Low quality history with poor current recall." Indicates item reviewed many times but poorly recalled." (let* ((total-repeats 1000) (meanq 2.0) - (result (org-drill-determine-next-interval-sm2 5 10 1.5 3 20 meanq total-repeats)) + (result (test-scheduler--call-sm2 5 10 1.5 3 20 meanq total-repeats)) (new-meanq (test-scheduler--extract-meanq result))) (should (numberp new-meanq)) ;; meanq should remain low given poor history @@ -387,7 +387,7 @@ Indicates item reviewed many times but poorly recalled." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-zero-last-interval () "Test SM2 with zero last-interval. Should handle as first review (n=1 case)." - (let* ((result (org-drill-determine-next-interval-sm2 0 1 2.5 4 0 4.0 0)) + (let* ((result (test-scheduler--call-sm2 0 1 2.5 4 0 4.0 0)) (interval (test-scheduler--extract-interval result))) (should (= interval 1)))) @@ -395,8 +395,8 @@ Should handle as first review (n=1 case)." "Test SM2 with float last-interval vs integer. Algorithm should handle both correctly." (let ((org-drill-add-random-noise-to-intervals-p nil)) - (let* ((result-float (org-drill-determine-next-interval-sm2 10.5 3 2.5 4 0 4.0 10)) - (result-int (org-drill-determine-next-interval-sm2 10 3 2.5 4 0 4.0 10)) + (let* ((result-float (test-scheduler--call-sm2 10.5 3 2.5 4 0 4.0 10)) + (result-int (test-scheduler--call-sm2 10 3 2.5 4 0 4.0 10)) (interval-float (test-scheduler--extract-interval result-float)) (interval-int (test-scheduler--extract-interval result-int))) (should (numberp interval-float)) @@ -408,9 +408,9 @@ Algorithm should handle both correctly." (ert-deftest test-org-drill-determine-next-interval-sm2-boundary-alternating-quality-pattern () "Test SM2 behavior with alternating quality (5, 0, 5, 0 pattern). Simulates inconsistent learning." - (let* ((result-1 (org-drill-determine-next-interval-sm2 1 2 2.5 5 0 5.0 1)) + (let* ((result-1 (test-scheduler--call-sm2 1 2 2.5 5 0 5.0 1)) (ef-1 (test-scheduler--extract-ef result-1)) - (result-2 (org-drill-determine-next-interval-sm2 6 3 ef-1 0 0 4.5 2)) + (result-2 (test-scheduler--call-sm2 6 3 ef-1 0 0 4.5 2)) (interval-2 (test-scheduler--extract-interval result-2)) (failures-2 (test-scheduler--extract-failures result-2))) ;; After perfect then fail, should reset interval @@ -442,18 +442,18 @@ quirk drops into a blocking debugger in batch mode, so a bare (ert-deftest test-org-drill-determine-next-interval-sm2-error-quality-above-max () "Quality above the 0-5 range trips the quality assertion." (test-scheduler--should-cl-assert - (org-drill-determine-next-interval-sm2 1 2 2.5 6 0 4.0 1))) + (test-scheduler--call-sm2 1 2 2.5 6 0 4.0 1))) (ert-deftest test-org-drill-determine-next-interval-sm2-error-quality-below-min () "Quality below the 0-5 range trips the quality assertion." (test-scheduler--should-cl-assert - (org-drill-determine-next-interval-sm2 1 2 2.5 -1 0 4.0 1))) + (test-scheduler--call-sm2 1 2 2.5 -1 0 4.0 1))) (ert-deftest test-org-drill-determine-next-interval-sm2-error-negative-n () "A negative repeat count trips the (> n 0) assertion. Note n=0 is normalized to 1 before the assert, so zero is not an error case." (test-scheduler--should-cl-assert - (org-drill-determine-next-interval-sm2 1 -1 2.5 4 0 4.0 1))) + (test-scheduler--call-sm2 1 -1 2.5 4 0 4.0 1))) (provide 'test-org-drill-determine-next-interval-sm2) ;;; test-org-drill-determine-next-interval-sm2.el ends here diff --git a/tests/testutil-scheduler.el b/tests/testutil-scheduler.el index 72811e8..70204b4 100644 --- a/tests/testutil-scheduler.el +++ b/tests/testutil-scheduler.el @@ -43,5 +43,19 @@ Use this name in Simple8 tests where the field is called `ease' not `ef'." "Extract the optimal-factor matrix (position 6) from an SM5 RESULT list." (nth 6 result)) +;;;; Call adapters +;; The schedulers now take an `org-drill-card-state' plus QUALITY rather than a +;; long positional list (org-drill #147). These adapters pack the positional +;; args into the struct so the test call sites keep reading as the documented +;; algorithm inputs, making each migration a one-symbol rename at the call. + +(defun test-scheduler--call-sm2 (last-interval n ef quality failures meanq total-repeats) + "Call the SM2 scheduler from positional args, packing them into a card-state." + (org-drill-determine-next-interval-sm2 + (make-org-drill-card-state + :last-interval last-interval :repetitions n :ease ef + :failures failures :meanq meanq :total-repeats total-repeats) + quality)) + (provide 'testutil-scheduler) ;;; testutil-scheduler.el ends here |
