aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThanos Apollo <[email protected]>2024-05-17 06:34:57 +0300
committerThanos Apollo <[email protected]>2024-05-17 06:34:57 +0300
commitb9c6c04e33ad2f541ab116dda9e460f21034a8eb (patch)
treeb7ca4e08d8b6347ffe475fb4ef65477af7801875
parentbd9de41126d8752d48d38b5b9b3680ef0cd6b735 (diff)
parent5f51fa5efe1f78b5eda98145c17c8af9372d855a (diff)
Release version 0.2.5HEAD0.2.5master
This version brings fixes for gnosis algorithm: Fix algorithm ff, give priority to deck ff over note's ff. Fix gnosis-vc-pull, by changing gnosis-db to defvar we can now update the value when we pull changes. Until the first 2 successful reviews, the next interval upon failure will be 0, meaning it will be reviewed the same day. Adjust success next interval to not be surpassed by failure, this would occur if user hadn't reviewed an item/used gnosis in a long time.
-rw-r--r--gnosis-algorithm.el29
-rw-r--r--gnosis.el51
2 files changed, 62 insertions, 18 deletions
diff --git a/gnosis-algorithm.el b/gnosis-algorithm.el
index ad663e4..075e669 100644
--- a/gnosis-algorithm.el
+++ b/gnosis-algorithm.el
@@ -123,13 +123,18 @@ Optional integer OFFSET is a number of days from the current date."
(+ offset (calendar-absolute-from-gregorian now))))))
(list (nth 2 date) (nth 0 date) (nth 1 date)))))
-(defun gnosis-algorithm-date-diff (date)
- "Find the difference between the current date and the given DATE.
+(defun gnosis-algorithm-date-diff (date &optional date2)
+ "Find the difference between DATE2 and DATE.
+
+If DATE2 is nil, current date will be used instead.
DATE format must be given as (year month day)."
- (let ((given-date (encode-time 0 0 0 (caddr date) (cadr date) (car date))))
- (- (time-to-days (current-time))
- (time-to-days given-date))))
+ (let* ((given-date (encode-time 0 0 0 (caddr date) (cadr date) (car date)))
+ (date2 (if date2 (encode-time 0 0 0 (caddr date2) (cadr date2) (car date2))
+ (current-time)))
+ (diff (- (time-to-days date2)
+ (time-to-days given-date))))
+ (if (>= diff 0) diff (error "`DATE2' must be higher than `DATE'"))))
(cl-defun gnosis-algorithm-next-ef (&key ef success increase decrease threshold
c-successes c-failures)
@@ -179,13 +184,21 @@ successful reviews."
;; This should only occur in testing env or when the user has made breaking changes.
(cl-assert (> (nth 2 ef) 1) "Total ef value must be above 1")
(let* ((ef (nth 2 gnosis-algorithm-ef))
+ ;; If last-interval is 0, use 1 instead.
+ (last-interval (if (<= last-interval 0) 1 last-interval))
(interval (cond ((and (= successful-reviews 0) success)
(car initial-interval))
((and (= successful-reviews 1) success)
(cadr initial-interval))
- (t (if success
- (* ef last-interval)
- (* failure-factor last-interval))))))
+ ;; If it's still on initial stage, review the
+ ;; same day
+ ((and (< successful-reviews 2) (not success)) 0)
+ (t (let* ((success-interval (* ef last-interval))
+ (failure-interval (* last-interval failure-factor)))
+ (if success success-interval
+ ;; Make sure failure interval is never
+ ;; higher than success
+ (min success-interval failure-interval)))))))
(gnosis-algorithm-date (round interval))))
diff --git a/gnosis.el b/gnosis.el
index 50c35f2..27c57e8 100644
--- a/gnosis.el
+++ b/gnosis.el
@@ -112,7 +112,7 @@ When nil, the image will be displayed at its original size."
(make-directory gnosis-dir)
(make-directory gnosis-images-dir))
-(defconst gnosis-db
+(defvar gnosis-db
(emacsql-sqlite-open (expand-file-name "gnosis.db" gnosis-dir))
"Gnosis database file.")
@@ -486,6 +486,27 @@ Set SPLIT to t to split all input given."
"Return id for DECK name."
(gnosis-get 'id 'decks `(= name ,deck)))
+(defun gnosis-get-deck--note (id &optional name)
+ "Get deck id for note ID.
+
+If NAME is t, return name of deck."
+ (let* ((id-clause `(= id ,id))
+ (deck (gnosis-get 'deck-id 'notes id-clause)))
+ (if name (gnosis--get-deck-name deck) deck)))
+
+(defun gnosis-get-deck-ff (id)
+ "Return failure factor for deck of ID."
+ (let* ((id-clause `(= id ,id))
+ (deck-ff (gnosis-get 'failure-factor 'decks id-clause)))
+ deck-ff))
+
+(defun gnosis-get-note-ff (id)
+ "Return failure factor for note ID."
+ (let ((deck-ff (gnosis-get-deck-ff (gnosis-get-deck--note id)))
+ (note-ff (gnosis-get 'ff 'review `(= id ,id))))
+ (if (and deck-ff (> deck-ff note-ff))
+ deck-ff
+ note-ff)))
(cl-defun gnosis-suspend-note (id)
"Suspend note with ID."
@@ -1080,20 +1101,33 @@ well."
due-notes)
:test #'equal)))
+(defun gnosis-review--get-offset (id)
+ "Return offset for note with value of id ID."
+ (let ((last-rev (gnosis-get 'last-rev 'review-log `(= id ,id))))
+ (gnosis-algorithm-date-diff last-rev)))
+
+(defun gnosis-review-last-interval (id)
+ "Return last review interval for note ID."
+ (let* ((where-id-clause `(= id ,id))
+ (last-rev (gnosis-get 'last-rev 'review-log where-id-clause))
+ (rev-date (gnosis-get 'next-rev 'review-log where-id-clause)))
+ (gnosis-algorithm-date-diff last-rev rev-date)))
+
(defun gnosis-review-algorithm (id success)
"Return next review date & ef for note with value of id ID.
SUCCESS is a boolean value, t for success, nil for failure.
Returns a list of the form ((yyyy mm dd) (ef-increase ef-decrease ef-total))."
- (let ((ff gnosis-algorithm-ff)
+ (let ((ff (gnosis-get-note-ff id))
(ef (gnosis-get 'ef 'review `(= id ,id)))
(t-success (gnosis-get 't-success 'review-log `(= id ,id))) ;; total successful reviews
(c-success (gnosis-get 'c-success 'review-log `(= id ,id))) ;; consecutive successful reviews
(c-fails (gnosis-get 'c-fails 'review-log `(= id ,id))) ;; consecutive failed reviews
;; (t-fails (gnosis-get 't-fails 'review-log `(= id ,id))) ;; total failed reviews
;; (review-num (gnosis-get 'n 'review-log `(= id ,id))) ;; total reviews
- (last-interval (max (gnosis-review--get-offset id) 1))) ;; last interval
+ ;; (last-interval (max (gnosis-review--get-offset id) 1))
+ (last-interval (gnosis-review-last-interval id))) ;; last interval
(list (gnosis-algorithm-next-interval :last-interval last-interval
:ef ef
:success success
@@ -1108,11 +1142,6 @@ Returns a list of the form ((yyyy mm dd) (ef-increase ef-decrease ef-total))."
:c-successes c-success
:c-failures c-fails))))
-(defun gnosis-review--get-offset (id)
- "Return offset for note with value of id ID."
- (let ((last-rev (gnosis-get 'last-rev 'review-log `(= id ,id))))
- (gnosis-algorithm-date-diff last-rev)))
-
(defun gnosis-review--update (id success)
"Update review-log for note with value of id ID.
@@ -1590,6 +1619,8 @@ to improve readability."
(defun gnosis-review ()
"Start gnosis review session."
(interactive)
+ ;; Refresh modeline
+ (setq gnosis-due-notes-total (length (gnosis-review-get-due-notes)))
(let ((review-type (funcall gnosis-completing-read-function "Review: " '("Due notes"
"Due notes of deck"
"Due notes of specified tag(s)"
@@ -1842,7 +1873,8 @@ DASHBOARD-TYPE: either 'Notes' or 'Decks' to display the respective dashboard."
("notes" (gnosis-dashboard-output-notes (gnosis-collect-note-ids)))
("decks" (gnosis-dashboard-output-decks))
("tags" (gnosis-dashboard-output-notes (gnosis-collect-note-ids :tags t)))
- ("search" (gnosis-dashboard-output-notes (gnosis-collect-note-ids :query (read-string "Search for note: "))))))
+ ("search" (gnosis-dashboard-output-notes
+ (gnosis-collect-note-ids :query (read-string "Search for note: "))))))
(tabulated-list-print t)))
(defun gnosis-db-init ()
@@ -1894,7 +1926,6 @@ DASHBOARD-TYPE: either 'Notes' or 'Decks' to display the respective dashboard."
(and (listp item) (eq (car item) :eval)
(string-prefix-p " G:" (format "%s" (eval (cadr item))))))
global-mode-string))
- (run-at-time "5 min" 300 #'(lambda () (setq gnosis-due-notes-total (length (gnosis-review-get-due-notes)))))
(force-mode-line-update)))
(define-derived-mode gnosis-mode special-mode "Gnosis"