summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThanos Apollo <[email protected]>2023-12-18 02:51:37 +0200
committerThanos Apollo <[email protected]>2023-12-18 02:51:37 +0200
commit5d69e1865abe2e2d721c22a606b3e2e18ddbd638 (patch)
tree4e4a26314d97e75ad72671427547d952c0219f90
parentb2d89acc3def18af88b83b7b0805b7916d79100a (diff)
Seperate gnosis-algorithm from gnosis.el
-rw-r--r--gnosis-algorithm.el127
-rw-r--r--gnosis.el93
2 files changed, 127 insertions, 93 deletions
diff --git a/gnosis-algorithm.el b/gnosis-algorithm.el
new file mode 100644
index 0000000..5cbca92
--- /dev/null
+++ b/gnosis-algorithm.el
@@ -0,0 +1,127 @@
+;;; gnosis-algorithm.el --- Spaced Repetition Algorithm for Gnosis -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Thanos Apollo
+
+;; Author: Thanos Apollo <[email protected]>
+;; Keywords: extensions
+;; URL: https://git.thanosapollo.org/gnosis
+;; Version: 0.0.1
+
+;; Package-Requires: ((emacs "27.2") (compat "29.1.4.2"))
+
+;; 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:
+
+;; Work in progress
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'calendar)
+
+(defcustom gnosis-interval '(1 3)
+ "Gnosis initial interval.
+
+Interval by which a new question is displayed or when it's ef is at 1.3.
+
+First item: First interval
+Second item: Second interval."
+ :group 'gnosis
+ :type 'list)
+
+(defcustom gnosis-algorithm-ef '(0.3 0.3)
+ "Gnosis easiness factor.
+
+First item : Increase factor
+Second item: Decrease factor"
+ :group 'gnosis
+ :type 'list)
+
+(defcustom gnosis-algorithm-ff 0.5
+ "Gnosis forgetting factor.
+
+Used to calcuate new interval for failed questions."
+ :group 'gnosis
+ :type 'float)
+
+
+(defun gnosis-algorithm-date (&optional offset)
+ "Return the current date in a list (year month day).
+Optional integer OFFSET is a number of days from the current date."
+ (let* ((now (decode-time))
+ (now (list (decoded-time-month now)
+ (decoded-time-day now)
+ (decoded-time-year now))))
+ (let ((date (if (zerop (or offset 0))
+ now
+ (calendar-gregorian-from-absolute
+ (+ offset (calendar-absolute-from-gregorian now))))))
+ (list (nth 2 date) (nth 0 date) (nth 1 date)))))
+
+
+(defun gnosis-algorithm-date-diff (year month day)
+ "Find the difference between the current date and the given date.
+
+The structure of the given date is (YEAR MONTH DAY)."
+ (let ((current-date (gnosis-algorithm-date))
+ (given-date (encode-time 0 0 0 day month year)))
+ (- (time-to-days (current-time))
+ (time-to-days given-date))))
+
+(defun gnosis-algorithm-e-factor (ef quality)
+ "Calculate new e-factor given existing EF and binary QUALITY, 0 or 1."
+ (cond
+ ((not (numberp quality))
+ (error "Invalid argument passed to gnosis-algorithm-e-factor"))
+ ((= quality 0) ;; If the quality score is 0 (fail), decrease the ef by a small penalty
+ (max 1.3 (- ef (cadr gnosis-ef))))
+ ((= quality 1) ;; If the quality score is 1 (pass), increase the ef by a small reward
+ (+ ef (car gnosis-ef)))
+ (t (error "Invalid quality score passed to gnosis-algorithm-e-factor"))))
+
+(defun gnosis-algorithm-next-interval (last-interval n ef success ff)
+ "Calculate next interval.
+- LAST-INTERVAL : The number of days since the item was last reviewed.
+- N : Number of times the item has been reviewed.
+- EF : Easiness Factor.
+- SUCCESS : Success of the recall, ranges from 0 (unsuccessful) to 1
+ (successful).
+- FF: Failure factor
+
+Returns a tuple: (INTERVAL N EF) where,
+- INTERVAL : The number of days until the item should next be reviewed.
+- N : Incremented by 1.
+- EF : Modified based on the recall success for the item."
+ (cl-assert (and (>= success 0)
+ (<= success 1)))
+ ;; Calculate the next easiness factor.
+ (let* ((next-ef (gnosis-algorithm-e-factor ef success))
+ ;; Calculate the next interval.
+ (interval
+ (cond
+ ;; Show item same day on the first review
+ ((= n 0) 0)
+ ;; Immediately next day if it's the first time review.
+ ((<= n 1) (car gnosis-interval))
+ ;; After 3 days if it's second review.
+ ((= n 2) (cadr gnosis-interval))
+ ;; Increase last interval by 1 if recall was successful. Keep last interval if unsuccessful.
+ (t (if (= success 1)
+ (* ef last-interval)
+ (* ff last-interval))))))
+ (list (round interval) (1+ n) next-ef)))
+
+(provide 'gnosis-algorithm)
+;;; gnosis-algorithm.el ends here
diff --git a/gnosis.el b/gnosis.el
index f27c66f..9687a64 100644
--- a/gnosis.el
+++ b/gnosis.el
@@ -41,31 +41,6 @@
:group 'external
:prefix "gnosis-")
-(defcustom gnosis-interval '(1 3)
- "Gnosis initial interval.
-
-Interval by which a new question is displayed or when it's ef is at 1.3.
-
-First item: First interval
-Second item: Second interval."
- :group 'gnosis
- :type 'list)
-
-(defcustom gnosis-ef '(0.3 0.3)
- "Gnosis easiness factor.
-
-First item : Increase factor
-Second item: Decrease factor"
- :group 'gnosis
- :type 'list)
-
-(defcustom gnosis-ff 0.5
- "Gnosis forgetting factor.
-
-Used to calcuate new interval for failed questions."
- :group 'gnosis
- :type 'float)
-
(defvar gnosis-db (emacsql-sqlite (concat user-emacs-directory "gnosis.db")))
(cl-defun gnosis--select (value table &optional (restrictions '1=1))
@@ -268,74 +243,6 @@ TAGS are used to organize questions."
(display-line-numbers-mode 0)
:lighter " gnosis-mode")
-;; Gnosis Algorithm ;;
-;;;;;;;;;;;;;;;;;;;;;;
-
-(defun gnosis-date-current (&optional offset)
- "Return the current date in a list (year month day).
-Optional integer OFFSET is a number of days from the current date."
- (let* ((now (decode-time))
- (now (list (decoded-time-month now)
- (decoded-time-day now)
- (decoded-time-year now))))
- (let ((date (if (zerop (or offset 0))
- now
- (calendar-gregorian-from-absolute
- (+ offset (calendar-absolute-from-gregorian now))))))
- (list (nth 2 date) (nth 0 date) (nth 1 date)))))
-
-(defun gnosis-date-difference (year month day)
- "Find the difference between the current date and the given date.
-
-The structure of the given date is (YEAR MONTH DAY)."
- (let ((current-date (gnosis-date-current))
- (given-date (encode-time 0 0 0 day month year)))
- (- (time-to-days (current-time))
- (time-to-days given-date))))
-
-(defun gnosis-calculate-e-factor (ef quality)
- "Calculate new e-factor given existing EF and binary QUALITY, 0 or 1."
- (cond
- ((not (numberp quality))
- (error "Invalid argument passed to gnosis-calculate-e-factor"))
- ((= quality 0) ;; If the quality score is 0 (fail), decrease the ef by a small penalty
- (max 1.3 (- ef (cadr gnosis-ef))))
- ((= quality 1) ;; If the quality score is 1 (pass), increase the ef by a small reward
- (+ ef (car gnosis-ef)))
- (t (error "Invalid quality score passed to gnosis-calculate-e-factor"))))
-
-(defun gnosis-calculate-next-interval (last-interval n ef success ff)
- "Calculate next interval.
-- LAST-INTERVAL : The number of days since the item was last reviewed.
-- N : Number of times the item has been reviewed.
-- EF : The 'easiness factor'.
-- SUCCESS : Success of the recall, ranges from 0 (unsuccessful) to 1
- (successful).
-- FF: Failure factor
-
-Returns a tuple: (INTERVAL N EF) where,
-- INTERVAL : The number of days until the item should next be reviewed.
-- N : Incremented by 1.
-- EF : Modified based on the recall success for the item."
- (cl-assert (and (>= success 0)
- (<= success 1)))
- ;; Calculate the next easiness factor.
- (let* ((next-ef (gnosis-calculate-e-factor ef success))
- ;; Calculate the next interval.
- (interval
- (cond
- ;; Show item same day on the first review
- ((= n 0) 0)
- ;; Immediately next day if it's the first time review.
- ((<= n 1) (car gnosis-interval))
- ;; After 3 days if it's second review.
- ((= n 2) (cadr gnosis-interval))
- ;; Increase last interval by 1 if recall was successful. Keep last interval if unsuccessful.
- (t (if (= success 1)
- (* ef last-interval)
- (* ff last-interval))))))
- (list (round interval) (1+ n) next-ef)))
-
(provide 'gnosis)
;;; gnosis.el ends here