Commits

eeeickythump  committed 30be932

- New option: org-drill-hide-item-headings-p. If non-nil, item headings will be made
invisible while each item is being tested.
- OF matrix entries are rounded to 3 decimal places.
- Item E-factors are not modified if the item is "failed" (in accordance with Dr Wozniak's description of
the SM5 algorithm).

  • Participants
  • Parent commits ee09da7

Comments (0)

Files changed (3)

 <title>Org-Drill</title>
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
 <meta name="generator" content="Org-mode"/>
-<meta name="generated" content="2011-03-25 11:53:49 "/>
+<meta name="generated" content="2011-04-04 10:18:44 "/>
 <meta name="author" content="Paul Sexton"/>
 <meta name="description" content=""/>
 <meta name="keywords" content=""/>
 
 
 <p>
+Item headings may contain information that "gives away" the answer to the item,
+either in the heading text or in tags. If you want item headings to be made
+invisible while each item is being tested, add:
+</p>
+
+
+
+<pre class="example">(setq org-drill-hide-item-headings-p t)
+</pre>
+
+
+
+<p>
 Org-Drill supports two different spaced repetition algorithms &ndash; SM5 (the
 default, implemented by <code>org-learn</code>) and SM2. SM2 is an earlier algorithm which
 remains very popular &ndash; Anki and Mnemosyne, two of the most popular spaced
 In org mode, comment lines start with '#'. The rest of the line is ignored by
 Org (apart from some special cases). You may sometimes want to put material in
 comments which you do not want to see when you are being tested on the
-item. For this reason, all comments are rendered invisible while items are
+item. For this reason, comments are always rendered invisible while items are
 being tested.
 </p>
 
 <div id="postamble">
 <p class="author"> Author: Paul Sexton
 </p>
-<p class="date"> Date: 2011-03-25 11:53:49 </p>
+<p class="date"> Date: 2011-04-04 10:18:44 </p>
 <p class="creator">HTML generated by org-mode 7.4 in emacs 23</p>
 </div>
 </div>
 (setq org-drill-use-visible-cloze-face-p t)
 #+END_EXAMPLE
 
+Item headings may contain information that "gives away" the answer to the item,
+either in the heading text or in tags. If you want item headings to be made
+invisible while each item is being tested, add:
+
+#+BEGIN_EXAMPLE
+(setq org-drill-hide-item-headings-p t)
+#+END_EXAMPLE
+
 Org-Drill supports two different spaced repetition algorithms -- SM5 (the
 default, implemented by =org-learn=) and SM2. SM2 is an earlier algorithm which
 remains very popular -- Anki and Mnemosyne, two of the most popular spaced
 In org mode, comment lines start with '#'. The rest of the line is ignored by
 Org (apart from some special cases). You may sometimes want to put material in
 comments which you do not want to see when you are being tested on the
-item. For this reason, all comments are rendered invisible while items are
+item. For this reason, comments are always rendered invisible while items are
 being tested.
 
 

File org-drill.el

   :group 'org-drill)
 
 
+(defface org-drill-hidden-cloze-face
+  '((t (:foreground "deep sky blue" :background "blue")))
+  "The face used to hide the contents of cloze phrases."
+  :group 'org-drill)
+
+
 (defcustom org-drill-use-visible-cloze-face-p
   nil
   "Use a special face to highlight cloze-deleted text in org mode
   :type 'boolean)
 
 
-(defface org-drill-hidden-cloze-face
-  '((t (:foreground "deep sky blue" :background "blue")))
-  "The face used to hide the contents of cloze phrases."
-  :group 'org-drill)
+(defcustom org-drill-hide-item-headings-p
+  nil
+  "Conceal the contents of the main heading of each item during drill
+sessions? You may want to enable this behaviour if item headings or tags
+contain information that could 'give away' the answer."
+  :group 'org-drill
+  :type 'boolean)
 
 
 (defcustom org-drill-new-count-color
                     face org-drill-hidden-cloze-face
                     window t))
 
-(setplist 'org-drill-hidden-comment-overlay
+(setplist 'org-drill-hidden-text-overlay
           '(invisible t))
 
 
   list)
 
 
+(defun round-float (floatnum fix)
+  "Round the floating point number FLOATNUM to FIX decimal places.
+Example: (round-float 3.56755765 3) -> 3.568"
+  (let ((n (expt 10 fix)))
+    (/ (float (round (* floatnum n))) n)))
+
+
 (defun time-to-inactive-org-timestamp (time)
   (format-time-string
    (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
 
 (defmacro with-hidden-comments (&rest body)
   `(progn
+     (if org-drill-hide-item-headings-p
+         (org-drill-hide-heading-at-point))
      (org-drill-hide-comments)
      (unwind-protect
          (progn
 
 
 (defun org-drill-goto-drill-entry-heading ()
-  "Move the point to the heading which hold the :drill: tag for this
+  "Move the point to the heading which holds the :drill: tag for this
 drill entry."
   (unless (org-at-heading-p)
     (org-back-to-heading))
   (assert (> n 0))
   (assert (and (>= quality 0) (<= quality 5)))
   (let ((next-ef (modify-e-factor ef quality))
+        (old-ef ef)
         (interval nil))
     (setq of-matrix
           (set-optimal-factor n next-ef of-matrix
-                              (modify-of (get-optimal-factor n ef of-matrix)
-                                         quality org-learn-fraction))
-          ef next-ef)
+                              (round-float
+                               (modify-of (get-optimal-factor n ef of-matrix)
+                                          quality org-learn-fraction)
+                               3)))     ; round OF to 3 d.p.
+
+    (setq ef next-ef)
 
     (cond
      ;; "Failed" -- reset repetitions to 0,
      ((<= quality org-drill-failure-quality)
-      (list -1 1 ef of-matrix))      ; Not clear if OF matrix is supposed to be
-                                     ; preserved
+      (list -1 1 old-ef of-matrix))     ; Not clear if OF matrix is supposed to
+                                        ; be preserved
      ;; For a zero-based quality of 4 or 5, don't repeat
      ((and (>= quality 4)
            (not org-learn-always-reschedule))
 
 ;;; Essentially copied from `org-learn.el', but modified to
 ;;; optionally call the SM2 function above.
-(defun org-drill-smart-reschedule (quality)
-  (interactive "nHow well did you remember the information (on a scale of 0-5)? ")
+(defun org-drill-smart-reschedule (quality &optional days-ahead)
+  "If DAYS-AHEAD is supplied it must be a positive integer. The
+item will be scheduled exactly this many days into the future."
   (let* ((learn-str (org-entry-get (point) "LEARN_DATA"))
 	 (learn-data (or (and learn-str
 			      (read learn-str))
                                               (nth 2 learn-data)
                                               quality
                                               (nth 3 learn-data)))))
+    (if (integerp days-ahead)
+        (setf (nth 0 learn-data) days-ahead))
     (org-entry-put (point) "LEARN_DATA" (prin1-to-string learn-data))
     (cond
      ((= 0 (nth 0 learn-data))
 
 
 (defun org-drill-hypothetical-next-review-date (quality)
+  "Returns an integer representing the number of days into the future
+that the current item would be scheduled, based on a recall quality
+of QUALITY."
   (let* ((learn-str (org-entry-get (point) "LEARN_DATA"))
 	 (learn-data (or (and learn-str
 			      (read learn-str))
       (nth 0 learn-data)))))
 
 
+(defun org-drill-hypothetical-next-review-dates ()
+  (let ((intervals nil))
+    (dotimes (q 6)
+      (push (max (or (car intervals) 0)
+                 (org-drill-hypothetical-next-review-date q))
+            intervals))
+    (reverse intervals)))
+
+
 (defun org-drill-reschedule ()
   "Returns quality rating (0-5), or nil if the user quit."
   (let ((ch nil)
         (input nil)
-        (next-review-date-3 (org-drill-hypothetical-next-review-date 3))
-        (next-review-date-4 (org-drill-hypothetical-next-review-date 4))
-        (next-review-date-5 (org-drill-hypothetical-next-review-date 5)))
+        (next-review-dates (org-drill-hypothetical-next-review-dates)))
     (save-excursion
       (while (not (memq ch '(?q ?e ?0 ?1 ?2 ?3 ?4 ?5)))
         (setq input (read-key-sequence
 5 - You remembered the item really easily. (+%s days)
 
 How well did you do? (0-5, ?=help, e=edit, t=tags, q=quit)"
-                                 next-review-date-3
-                                 next-review-date-4
-                                 next-review-date-5)
+                                 (nth 3 next-review-dates)
+                                 (nth 4 next-review-dates)
+                                 (nth 5 next-review-dates))
                        "How well did you do? (0-5, ?=help, e=edit, q=quit)")))
         (cond
          ((stringp input)
       (let ((quality (- ch ?0))
             (failures (org-entry-get (point) "DRILL_FAILURE_COUNT")))
         (save-excursion
-          (org-drill-smart-reschedule quality))
+          (org-drill-smart-reschedule quality
+                                      (nth quality next-review-dates)))
         (push quality *org-drill-session-qualities*)
         (cond
          ((<= quality org-drill-failure-quality)
     (org-in-regexp regexp nlines)))
 
 
+(defun org-drill-hide-region (beg end)
+  "Hide the buffer region between BEG and END with an 'invisible text'
+visual overlay."
+  (let ((ovl (make-overlay beg end)))
+    (overlay-put ovl 'category
+                 'org-drill-hidden-text-overlay)))
+
+
+(defun org-drill-hide-heading-at-point ()
+  (unless (org-at-heading-p)
+    (error "Point is not on a heading."))
+  (save-excursion
+    (let ((beg (point)))
+      (end-of-line)
+      (org-drill-hide-region beg (point)))))
+
+
 (defun org-drill-hide-comments ()
   (save-excursion
     (while (re-search-forward "^#.*$" nil t)
-      (org-drill-hide-comment))))
-
-
-(defun org-drill-hide-comment ()
-  "Hide the current match with a 'cloze' visual overlay."
-  (let ((ovl (make-overlay (match-beginning 0) (match-end 0))))
-    (overlay-put ovl 'category
-                 'org-drill-hidden-comment-overlay)))
+      (org-drill-hide-region (match-beginning 0) (match-end 0)))))
 
 
 (defun org-drill-unhide-comments ()
+  ;; This will also unhide the item's heading.
   (save-excursion
     (dolist (ovl (overlays-in (point-min) (point-max)))
-      (when (eql 'org-drill-hidden-comment-overlay (overlay-get ovl 'category))
+      (when (eql 'org-drill-hidden-text-overlay (overlay-get ovl 'category))
         (delete-overlay ovl)))))