diff options
-rw-r--r-- | org-fc-algo-sm2.el | 114 | ||||
-rw-r--r-- | org-fc-compat.el | 36 | ||||
-rw-r--r-- | org-fc.el | 79 |
3 files changed, 155 insertions, 74 deletions
diff --git a/org-fc-algo-sm2.el b/org-fc-algo-sm2.el new file mode 100644 index 0000000..75fce9a --- /dev/null +++ b/org-fc-algo-sm2.el @@ -0,0 +1,114 @@ +;;; org-fc-algo-sm2.el --- Variation of SM2 spacing algorithm -*- lexical-binding: t; -*- + +;; Copyright (C) 2020 Leon Rische + +;; Author: Leon Rische <emacs@leonrische.me> + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: +;; +;; +;; +;;; Code: + +;;;; Parameters + +(defcustom org-fc-algo-sm2-changes + '((again . -0.3) + (hard . -0.15) + (good . 0.0) + (easy . 0.15)) + "Changes to a cards ease depending on its rating." + :type 'list + :group 'org-fc) + +(defcustom org-fc-algo-sm2-fixed-intervals + '(0.0 0.01 1.0 6.0) + "Hard-coded intervals for the first few card boxes. +Values are in days." + :type 'list + :group 'org-fc) + +(defcustom org-fc-algo-sm2-ease-min 1.3 "Lower bound for a cards ease." + :type 'float + :group 'org-fc) + +(defcustom org-fc-algo-sm2-ease-initial 2.5 "Initial ease." + :type 'float + :group 'org-fc) + +(defcustom org-fc-algo-sm2-ease-max 5.0 "Upper bound for a cards ease." + :type 'float + :group 'org-fc) + +(defcustom org-fc-algo-sm2-fuzz-min 0.9 + "Lower bound for random interval fuzz factor." + :type 'float + :group 'org-fc) + +(defcustom org-fc-algo-sm2-fuzz-max 1.1 + "Upper bound for random interval fuzz factor." + :type 'float + :group 'org-fc) + +;;;; Helper Functions + +(defun org-fc-algo-sm2-fuzz (interval) + "Apply fuzz to INTERVAL. +INTERVAL is by a random factor between `org-fc-sm2-fuzz-min' and +`org-fc-sm2-fuzz-max'" + (* + interval + (+ org-fc-sm2-fuzz-min + (cl-random (- org-fc-sm2-fuzz-max org-fc-sm2-fuzz-min))))) + +;;;; Main Algorithm + +(defun org-fc-algo-sm2-next-parameters (ease box interval rating) + "Calculate the next parameters of a card, based on the review RATING. +EASE, BOX and INTERVAL are the current parameters of the card." + (let* ((next-ease + (if (< box 2) + ease + (min + (max + (+ ease (alist-get rating org-fc-sm2-changes)) + org-fc-sm2-ease-min) + org-fc-sm2-ease-max))) + (next-box + (cond + ;; If a card is rated easy, skip the learning phase + ((and (eq box 0) (eq rating 'easy)) 2) + ;; If the review failed, go back to box 0 + ((eq rating 'again) 0) + ;; Otherwise, move forward one box + (t (1+ box)))) + (next-interval + (cond ((< next-box (length org-fc-sm2-fixed-intervals)) + (nth next-box org-fc-sm2-fixed-intervals)) + ((and (eq org-fc-algorithm 'sm2-v2) (eq rating 'hard)) (* 1.2 interval)) + (t (org-fc-sm2-fuzz (* next-ease interval)))))) + (list next-ease next-box next-interval))) + +(defun org-fc-algo-sm2-initial-review-data (position) + "Initial SM2 review data for POSITION." + (list position org-fc-sm2-ease-initial 0 0 + (org-fc-timestamp-now))) + +;;; Footer + +(provide 'org-fc-algo-sm2) + +;;; org-fc-algo-sm2.el ends here diff --git a/org-fc-compat.el b/org-fc-compat.el index abd3d2a..2aa98ab 100644 --- a/org-fc-compat.el +++ b/org-fc-compat.el @@ -39,6 +39,42 @@ 'org-fc--hashtable-to-alist 'org-fc-dashboard--hashtable-to-alist "0.0.1") +(define-obsolete-function-alias + 'org-fc-sm2-fuzz + 'org-fc-algo-sm2-fuzz) + +(define-obsolete-function-alias + 'org-fc-sm2-next-parameters + 'org-fc-algo-sm2-next-parameters) + +(define-obsolete-variable-alias + 'org-fc-sm2-changes + 'org-fc-algo-sm2-changes) + +(define-obsolete-variable-alias + 'org-fc-sm2-fixed-intervals + 'org-fc-algo-sm2-fixed-intervals) + +(define-obsolete-variable-alias + 'org-fc-sm2-ease-min + 'org-fc-algo-sm2-ease-min) + +(define-obsolete-variable-alias + 'org-fc-sm2-ease-max + 'org-fc-algo-sm2-ease-max) + +(define-obsolete-variable-alias + 'org-fc-sm2-ease-initial + 'org-fc-algo-sm2-ease-initial) + +(define-obsolete-variable-alias + 'org-fc-sm2-fuzz-min + 'org-fc-algo-sm2-fuzz-min) + +(define-obsolete-variable-alias + 'org-fc-sm2-fuzz-max + 'org-fc-algo-sm2-fuzz-max) + ;;; Footer (provide 'org-fc-compat) @@ -133,42 +133,6 @@ types." :type '(choice (const sm2-v1) (const sm2-v2)) :group 'org-fc) -(defcustom org-fc-sm2-changes - '((again . -0.3) - (hard . -0.15) - (good . 0.0) - (easy . 0.15)) - "Changes to a cards ease depending on its rating." - :type 'list - :group 'org-fc) - -(defcustom org-fc-sm2-fixed-intervals - '(0.0 0.01 1.0 6.0) - "Hard-coded intervals for the first few card boxes. -Values are in days." - :type 'list - :group 'org-fc) - -(defcustom org-fc-sm2-ease-min 1.3 "Lower bound for a cards ease." - :type 'float - :group 'org-fc) -(defcustom org-fc-sm2-ease-initial 2.5 "Initial ease." - :type 'float - :group 'org-fc) -(defcustom org-fc-sm2-ease-max 5.0 "Upper bound for a cards ease." - :type 'float - :group 'org-fc) - -(defcustom org-fc-sm2-fuzz-min 0.9 - "Lower bound for random interval fuzz factor." - :type 'float - :group 'org-fc) - -(defcustom org-fc-sm2-fuzz-max 1.1 - "Upper bound for random interval fuzz factor." - :type 'float - :group 'org-fc) - (defcustom org-fc-bury-siblings nil "If non-nil, show at most one position of a card per review. Does not apply to cloze single and cloze enumeration cards." @@ -892,42 +856,8 @@ Positions are shuffled in a way that preserves the order of the (sort positions (lambda (a b) (> (car a) (car b))))))) ;;; Review & Spacing -;;;; Spacing Algorithm (SM2) - -(defun org-fc-sm2-fuzz (interval) - "Apply fuzz to INTERVAL. -INTERVAL is by a random factor between `org-fc-sm2-fuzz-min' and -`org-fc-sm2-fuzz-max'" - (* - interval - (+ org-fc-sm2-fuzz-min - (cl-random (- org-fc-sm2-fuzz-max org-fc-sm2-fuzz-min))))) - -(defun org-fc-sm2-next-parameters (ease box interval rating) - "Calculate the next parameters of a card, based on the review RATING. -EASE, BOX and INTERVAL are the current parameters of the card." - (let* ((next-ease - (if (< box 2) - ease - (min - (max - (+ ease (alist-get rating org-fc-sm2-changes)) - org-fc-sm2-ease-min) - org-fc-sm2-ease-max))) - (next-box - (cond - ;; If a card is rated easy, skip the learning phase - ((and (eq box 0) (eq rating 'easy)) 2) - ;; If the review failed, go back to box 0 - ((eq rating 'again) 0) - ;; Otherwise, move forward one box - (t (1+ box)))) - (next-interval - (cond ((< next-box (length org-fc-sm2-fixed-intervals)) - (nth next-box org-fc-sm2-fixed-intervals)) - ((and (eq org-fc-algorithm 'sm2-v2) (eq rating 'hard)) (* 1.2 interval)) - (t (org-fc-sm2-fuzz (* next-ease interval)))))) - (list next-ease next-box next-interval))) + +(require 'org-fc-algo-sm2) ;;;; Demo Mode @@ -1083,8 +1013,9 @@ END is the start of the line with :END: on it." (defun org-fc-review-data-default (position) "Default review data for position POSITION." - (list position org-fc-sm2-ease-initial 0 0 - (org-fc-timestamp-now))) + (case org-fc-algorithm + ('sm2-v1 (org-fc-algo-sm2-initial-review-data position)) + ('sm2-v2 (org-fc-algo-sm2-initial-review-data position)))) (defun org-fc-review-data-update (positions) "Update review data to POSITIONS. |