Anonymous avatar Anonymous committed bc74045

Added implementation of SM2 algorithm.
Add option 'org-drill-spaced-repetition-algorithm': choose either SM2 or SM5 algorithm.
Add option 'org-drill-add-random-noise-to-intervals-p': randomly vary repetition intervals slightly, to avoid clumping.
Fixed a bug in org-learn's SM5 algorithm (intervals much too long).
Use overlays to display cloze deletions as '[...]' during reviews.
Cloze text can contain hints, which will visible during review.
Add option 'org-drill-failure-quality': customise which quality is regarded as unambiguous failure (1 or 2).
Expanded documentation, and added section on 'incremental reading', with example setup.

Comments (0)

Files changed (4)

 <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="2010-08-22 09:45:05 NZST"/>
+<meta name="generated" content="2010-08-26 21:14:57 NZST"/>
 <meta name="author" content="Paul Sexton"/>
 <meta name="description" content=""/>
 <meta name="keywords" content=""/>
  }
 /*]]>*///-->
 </script>
+
 </head>
 <body>
 <div id="content">
 <div id="text-table-of-contents">
 <ul>
 <li><a href="#sec-1">1 Synopsis </a></li>
-<li><a href="#sec-2">2 Installation </a></li>
+<li><a href="#sec-2">2 Installation and Customisation </a></li>
 <li><a href="#sec-3">3 Demonstration </a></li>
 <li><a href="#sec-4">4 Writing the questions </a>
 <ul>
 </div>
 
 <div id="outline-container-2" class="outline-2">
-<h2 id="sec-2"><span class="section-number-2">2</span> Installation </h2>
+<h2 id="sec-2"><span class="section-number-2">2</span> Installation and Customisation </h2>
 <div class="outline-text-2" id="text-2">
 
 
 
 
 
-<pre class="src src-emacs-lisp"><span style="color: #696969;">(</span><span style="color: #8b4789;">require</span> '<span style="color: #698b22; font-weight: bold;">org-drill</span><span style="color: #696969;">)</span>
+<pre class="example">(require 'org-drill)
 </pre>
 
 
 
 <p>
 I also recommend the following, so that items are always eventually retested,
-even when you remember them very well.
+even when you remember them well.
 </p>
 
 
 
-<pre class="src src-emacs-lisp"><span style="color: #696969;">(</span>setq org-learn-always-reschedule t<span style="color: #696969;">)</span>
+<pre class="example">(setq org-learn-always-reschedule t)
 </pre>
 
 
 
 
 
-<pre class="src src-emacs-lisp"><span style="color: #696969;">(</span>setq org-drill-use-visible-cloze-face-p t<span style="color: #696969;">)</span>
+<pre class="example">(setq org-drill-use-visible-cloze-face-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
+repetition programs, use SM2.
+</p>
+<p>
+If you want Org-Drill to use the SM2 algorithm, put the following in your
+<code>.emacs</code>:
+</p>
+
+
+
+<pre class="example">(setq org-drill-spaced-repetition-algorithm 'sm2)
+</pre>
+
+
+
+<p>
+The intervals generated by the SM2 and SM5 algorithms are pretty
+deterministic. If you tend to add items in large, infrequent batches, the lack
+of variation in interval scheduling can lead to the problem of "lumpiness" --
+one day a large batch of items are due for review, the next there is almost
+nothing, a few days later another big pile of items is due.
+</p>
+<p>
+This problem can be ameliorated by adding some random "noise" to the interval
+scheduling algorithm. The author of SuperMemo actually recommends this approach
+for the SM5 algorithm, and Org-Drill's implementation uses <a href="http://www.supermemo.com/english/ol/sm5.htm">his code</a>.
+</p>
+<p>
+To enable random "noise" for item intervals, set the variable
+<code>org-drill-add-random-noise-to-intervals-p</code> to true by putting the following in
+your <code>.emacs</code>:
+</p>
+
+
+
+<pre class="example">(setq org-drill-add-random-noise-to-intervals-p t)
 </pre>
 
 
 </p>
 <blockquote>
 
-<p>The capital city of Estonia is <font style="background-color: blue;" color="blue">
-XXXXXXX</font>.
+<p>The capital city of Estonia is <font style="background-color: blue;" color="cyan">
+<tt>[&hellip;]</tt></font>.
 </p>
 </blockquote>
 
 <p>
 When the user presses a key, the text "Tallinn" will become visible.
 </p>
+<p>
+Clozed text can also contain a "hint" about the answer. If the text 
+surrounded by single square brackets contains a `|' character (vertical bar),
+all text after that character is treated as a hint, and will be visible when
+the rest of the text is hidden.
+</p>
+<p>
+Example:
+</p>
+
+
+
+<pre class="example">Type 1 hypersensitivity reactions are mediated by [immunoglobulin E|molecule]
+and [mast cells|cell type].
+</pre>
+
+
+
+<blockquote>
+
+<p>Type 1 hypersensitivity reactions are mediated by 
+<font style="background-color: blue;" color="cyan">
+<tt>[&hellip;molecule]</tt></font>
+and <font style="background-color: blue;" color="cyan">
+<tt>[&hellip;cell type]</tt></font>.
+</p>
+</blockquote>
+
+
 
 </div>
 
 rate your recall of it by pressing a key between 0 and 5. The meaning of these
 numbers is (taken from <code>org-learn</code>):
 </p>
-<dl>
-<dt>0</dt><dd>
-Completely forgot. 
-</dd>
-<dt>1</dt><dd>
-Even after seeing the answer, it still took a bit to sink in. 
-</dd>
-<dt>2</dt><dd>
-After seeing the answer, you remembered it. 
-</dd>
-<dt>3</dt><dd>
-It took you awhile, but you finally remembered.
-</dd>
-<dt>4</dt><dd>
-After a little bit of thought you remembered.
-</dd>
-<dt>5</dt><dd>
-You remembered the item really easily.
+<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
+<caption></caption>
+<colgroup><col align="right" /><col align="left" /><col align="left" />
+</colgroup>
+<thead>
+<tr><th scope="col">Quality</th><th scope="col">SuperMemo label</th><th scope="col">Meaning</th></tr>
+</thead>
+<tbody>
+<tr><td>0</td><td>NULL</td><td>You have forgotten this card completely.</td></tr>
+<tr><td>1</td><td>BAD</td><td>Wrong answer.</td></tr>
+<tr><td>2</td><td>FAIL</td><td>Barely correct, the interval was too long.</td></tr>
+<tr><td>3</td><td>PASS</td><td>Correct answer, but with much effort.</td></tr>
+<tr><td>4</td><td>GOOD</td><td>Correct answer, with a little thought.</td></tr>
+<tr><td>5</td><td>BRIGHT</td><td>Correct answer, effortless.</td></tr>
+</tbody>
+</table>
 
-</dd>
-</dl>
 
-<p>You can press '?'  at the prompt if you have trouble remembering what the
+<p>
+You can press '?'  at the prompt if you have trouble remembering what the
 numbers 0&ndash;5 signify. At any time you can press 'q' to finish the drill early
 (your progress will be saved), or 'e' to finish the drill and jump to the
 current topic for editing (your progress up to that point will be saved).
 Much of the infrastructure for incremental reading is already provided by Org
 Mode, with the help of some other emacs packages. You can provide yourself with
 an incremental reading facility by using 'org-capture' alongside a package that
-allows you to browse web pages in emacs &ndash; e.g. w3 or <a href="http://www.emacswiki.org/emacs/emacs-w3m">emacs-w3m</a>. There is a
-large variety of bookmarking packages for emacs which allow you to save your
-place in webpages (another important component of incremental reading). See the
-<a href="http://www.emacswiki.org/emacs/BookMarks">Emacs Wiki</a> for details.
+allows you to browse web pages either in emacs (w3 or <a href="http://www.emacswiki.org/emacs/emacs-w3m">emacs-w3m</a>) or in the
+external browser of your choice (<a href="http://orgmode.org/worg/org-contrib/org-protocol.php">org-protocol</a>).
+</p>
+<p>
+Another important component of incremental reading is the ability to save your
+exact place in a document, so you can read it <i>incrementally</i> rather than all
+at once. There is a large variety of bookmarking packages for emacs which
+provide advanced bookmarking functionality: see the <a href="http://www.emacswiki.org/emacs/BookMarks">Emacs Wiki</a> for details.
+Bookmarking exact webpage locations in an external browser is a bit more
+difficult. For Firefox, the addon works well.
 </p>
 <p>
 An example of using Org-Drill for incremental reading is given below. First,
-and most importantly, we need to define an <code>org-capture</code> template for captured
-facts:
+and most importantly, we need to define a couple of <code>org-capture</code> templates for
+captured facts. 
 </p>
 
 
 
-<pre class="src src-emacs-lisp"><span style="color: #696969;">(</span>setq org-capture-templates
-      `<span style="color: #696969;">((</span><span style="color: #008b00;">"f"</span> <span style="color: #008b00;">"Fact"</span> entry
-         <span style="color: #696969;">(</span>file+headline <span style="color: #008b00;">"my_new_facts.org"</span> <span style="color: #008b00;">"Incoming"</span><span style="color: #696969;">)</span>
-         <span style="color: #696969;">(</span>concat <span style="color: #008b00;">"* Fact #%(format \"%s\" (float-time))        :"</span>
-                 org-drill-question-tag
-                 <span style="color: #008b00;">":%^g\n
-    :PROPERTIES:
-    :DATE_ADDED: %t
-    :SOURCE_URL: %a
-    :END:\n
-%i%?\n\n"</span><span style="color: #696969;">)</span>
-         <span style="color: #4169e1;">:empty-lines</span> 1
-         <span style="color: #4169e1;">:immediate-finish</span> nil<span style="color: #696969;">)</span>
-        <span style="color: #db7093;">;; </span><span style="color: #db7093;">...other capture templates...
-</span>    <span style="color: #696969;">))</span>
+<pre class="example">(setq org-capture-templates
+       `(("u"
+         "Task: Read this URL"
+         entry
+         (file+headline "tasks.org" "Articles To Read")
+         ,(concat "* TODO Read article: '%:description'\nURL: %c\n\n")
+         :empty-lines 1
+         :immediate-finish t)
+
+        ("w"
+         "Capture web snippet"
+         entry
+         (file+headline "my-facts.org" "Inbox")
+         ,(concat "* Fact: '%:description'        :"
+                  (format "%s" org-drill-question-tag)
+                  ":\n:PROPERTIES:\n:DATE_ADDED: %u\n:SOURCE_URL: %c\n:END:\n\n%i\n%?\n")
+         :empty-lines 1
+         :immediate-finish t)
+        ;; ...other capture templates...
+    ))
 </pre>
 
 
 
 <p>
-Using this template, you can select a region of text which contains a fact you
-want to remember, for example while reading a web page. You then invoke the
-capture template above, and the selected text will be turned into a new fact
-and saved to whichever file and heading you nominate in the template. You will
-be given the opportunity to edit the fact &ndash; you should make sure that the fact
-makes sense independent of its context, as that is how it will be presented to
-you. The easiest way to turn the text into a 'question' is by cloze
-deletion. All you need to do is surround the 'hidden' parts of the text with
-square brackets. 
-</p>
-<p>
-Next, you start reading a web page within Emacs. For example, suppose you are
-reading the Wikipedia entry on tuberculosis <a href="http://en.wikipedia.org/wiki/Tuberculosis">here</a>.
+Using these templates and <code>org-protocol</code>, you can set up buttons in your web
+browser to:
+</p><ul>
+<li>
+Create a task telling you to read the URL of the currently viewed webpage
+</li>
+<li>
+Turn a region of selected text on a webpage, into a new fact which is saved
+to whichever file and heading you nominate in the template. The fact will
+contain a timestamp, and a hyperlink back to the webpage where you created
+it.
+
+</li>
+</ul>
+
+<p>For example, suppose you are reading the Wikipedia entry on tuberculosis <a href="http://en.wikipedia.org/wiki/Tuberculosis">here</a>.
 </p>
 <p>
 You read the following:
 
 <p>
 You decide you want to remember that "Bacillus Calmette-Guérin vaccine" is the
-name of the vaccine against tuberculosis. First, you select the relevant
-portion of the text as the active region:
+name of the vaccine against tuberculosis. First, you select the `interesting'
+portion of the text with the mouse:
 </p>
 <blockquote>
 
 
 
 <p>
-Then you press a key to "capture" this piece of text (whatever key you have
-bound to <code>org-capture</code>), followed by "f" to use the "Fact" template shown
-above. 
+Then you press the button you created when setting up <code>org=protocol</code>, which is
+configured to activate the capture template "w: Capture web snippet". The
+selected text will be sent to Emacs, turned into a new fact using the template,
+and filed away for your later attention.
 </p>
 <p>
-A temporary buffer will be created, containing something like:
+(Note that it might be more efficient to turn the entire paragraph into a drill
+item &ndash; since it contains several important facts &ndash; then split it up into
+multiple items when you edit it later in Emacs.)
+</p>
+<p>
+Once you have had enough of reading the article, save your place, then go to
+your "fact" file in Emacs. You should see that all the pieces of text you
+selected have been turned into drill items. Continuing the above example, you
+would see something like:
 </p>
 
 
 
-<pre class="example">** Fact #1282372386.671655                           :drill:
-
-    :PROPERTIES:
-    :DATE_ADDED: &lt;2010-08-21 Sat&gt;
-    :SOURCE_URL: [[http://en.wikipedia.org/wiki/Tuberculosis][Tuberculosis - Wikipedia, the free encyclopedia]]
-    :END:
+<pre class="example">** Fact: 'Tuberculosis - Wikipedia, the Free Encyclopedia'        :drill:
 
 Prevention relies on screening programs and vaccination, usually with Bacillus
 Calmette-Guérin vaccine.
 
 
 <p>
-Note that the fact's properties automatically contain the date of its creation,
-and a URL linking back to the origin of the fact &ndash; the web page you were
-browsing, in this case. Because fact "titles" are seldom necessary, the title
-of the fact contains a meaningless but unique number (the number of seconds
-elapsed since 1/1/1970).
-</p>
-<p>
-Next, you edit the sentence so that it makes sense when you are presented with
-it out of context, and you also mark the key fact you want to remember by
-surrounding it with single square brackets.
+You need to edit this fact so it makes sense independent of its context, as
+that is how it will be presented to you in future. The easiest way to turn the
+text into a 'question' is by cloze deletion. All you need to do is surround the
+'hidden' parts of the text with square brackets.
 </p>
 <pre class="example">
 Prevention of tuberculosis relies on screening programs and vaccination,
 </pre>
 
 
+
 <p>
-You then press <code>C-c C-c</code>, and the new fact is saved. You continue reading the
-web page, adding other facts if you wish.
+You can of course define browser buttons that use several different "fact"
+templates, each of which might send its fact to a different file or subheading,
+or give it different tags or properties, for example. 
 </p>
-<p>
-Points to note:
-</p><ul>
-<li>
-You can of course define several different "fact" templates, each of which
-might send its fact to a different file or subheading, or give it different
-tags or properties, for example.
-</li>
-<li>
-You don't have to use a web browser within Emacs. The "fact" template above
-will work if you do not have text selected &ndash; the new fact will be empty. You
-could read a web page (or PDF document, etc) in a program of your choice,
-copy some text to the clipboard, then switch to Emacs and paste it into a new
-empty fact.
-</li>
-<li>
-Alternatively, you could define a template that takes its text from the
-clipboard rather than from the selected region. You can do this by changing
-the <code>%i</code> in the fact template to <code>%x</code> or <code>%^C</code>. See the documentation for the
-variable <code>org-capture-templates</code> for more details.
 
-
-</li>
-</ul>
 </div>
 
 </div>
 <div class="outline-text-2" id="text-8">
 
 
-
 <ul>
 <li>
-hide drawers.
+hide drawers!
 </li>
 <li>
 <code>org-drill-question-tag</code> should use a tag match string, rather than a
 </li>
 <li>
 perhaps take account of item priorities, showing high priority items first
-
 </li>
 </ul>
 </div>
 <div id="postamble">
 <p class="author"> Author: Paul Sexton
 </p>
-<p class="date"> Date: 2010-08-22 09:45:05 NZST</p>
+<p class="date"> Date: 2010-08-26 21:14:57 NZST</p>
 <p class="creator">HTML generated by org-mode 7.01trans in emacs 23</p>
 </div>
 </div>
 # -*- mode: org; coding: utf-8 -*-
+#+STARTUP: showall
 #+TITLE: Org-Drill
 #+AUTHOR: Paul Sexton
 
 - [[http://mnemosyne-proj.org/index.php][Mnemosyne]]
 
 
-* Installation
+* Installation and Customisation
 
 
 Put the following in your =.emacs=. You will also need to make sure that Org's
 "contrib/lisp" directory is in the emacs load-path.
 
-#+BEGIN_SRC emacs-lisp 
+#+BEGIN_EXAMPLE
 (require 'org-drill)
-#+END_SRC
+#+END_EXAMPLE
 
 I also recommend the following, so that items are always eventually retested,
-even when you remember them very well.
+even when you remember them well.
 
-#+BEGIN_SRC emacs-lisp 
+#+BEGIN_EXAMPLE
 (setq org-learn-always-reschedule t)
-#+END_SRC
+#+END_EXAMPLE
 
 If you want cloze-deleted text to show up in a special font within Org mode
 buffers, also add:
 
-#+BEGIN_SRC emacs-lisp 
+#+BEGIN_EXAMPLE
 (setq org-drill-use-visible-cloze-face-p t)
-#+END_SRC
+#+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
+repetition programs, use SM2.
+
+If you want Org-Drill to use the SM2 algorithm, put the following in your
+=.emacs=:
+
+#+BEGIN_EXAMPLE
+(setq org-drill-spaced-repetition-algorithm 'sm2)
+#+END_EXAMPLE
+
+The intervals generated by the SM2 and SM5 algorithms are pretty
+deterministic. If you tend to add items in large, infrequent batches, the lack
+of variation in interval scheduling can lead to the problem of "lumpiness" --
+one day a large batch of items are due for review, the next there is almost
+nothing, a few days later another big pile of items is due.
+
+This problem can be ameliorated by adding some random "noise" to the interval
+scheduling algorithm. The author of SuperMemo actually recommends this approach
+for the SM5 algorithm, and Org-Drill's implementation uses [[http://www.supermemo.com/english/ol/sm5.htm][his code]].
+
+To enable random "noise" for item intervals, set the variable
+=org-drill-add-random-noise-to-intervals-p= to true by putting the following in
+your =.emacs=:
+
+#+BEGIN_EXAMPLE
+(setq org-drill-add-random-noise-to-intervals-p t)
+#+END_EXAMPLE
 
 
 * Demonstration
 During review, the user will see:
 
 #+BEGIN_QUOTE
-The capital city of Estonia is @<font style="background-color: blue;" color="blue">
-XXXXXXX@</font>.
+The capital city of Estonia is @<font style="background-color: blue;" color="cyan">
+@<tt>[...]@</tt>@</font>.
 #+END_QUOTE
 
 When the user presses a key, the text "Tallinn" will become visible.
 
+Clozed text can also contain a "hint" about the answer. If the text 
+surrounded by single square brackets contains a `|' character (vertical bar),
+all text after that character is treated as a hint, and will be visible when
+the rest of the text is hidden.
+
+Example:
+
+#+BEGIN_EXAMPLE
+Type 1 hypersensitivity reactions are mediated by [immunoglobulin E|molecule]
+and [mast cells|cell type].
+#+END_EXAMPLE
+
+#+BEGIN_QUOTE
+Type 1 hypersensitivity reactions are mediated by 
+@<font style="background-color: blue;" color="cyan">
+@<tt>[...molecule]@</tt>@</font>
+and @<font style="background-color: blue;" color="cyan">
+@<tt>[...cell type]@</tt>@</font>.
+#+END_QUOTE
+
 
 ** Two-sided cards
 
 rate your recall of it by pressing a key between 0 and 5. The meaning of these
 numbers is (taken from =org-learn=):
 
-- 0 :: Completely forgot. 
-- 1 :: Even after seeing the answer, it still took a bit to sink in. 
-- 2 :: After seeing the answer, you remembered it. 
-- 3 :: It took you awhile, but you finally remembered.
-- 4 :: After a little bit of thought you remembered.
-- 5 :: You remembered the item really easily.
+| Quality | SuperMemo label | Meaning                                    |
+|---------+-----------------+--------------------------------------------|
+|       0 | NULL            | You have forgotten this card completely.   |
+|       1 | BAD             | Wrong answer.                              |
+|       2 | FAIL            | Barely correct, the interval was too long. |
+|       3 | PASS            | Correct answer, but with much effort.      |
+|       4 | GOOD            | Correct answer, with a little thought.     |
+|       5 | BRIGHT          | Correct answer, effortless.                |
 
 You can press '?'  at the prompt if you have trouble remembering what the
 numbers 0--5 signify. At any time you can press 'q' to finish the drill early
 Much of the infrastructure for incremental reading is already provided by Org
 Mode, with the help of some other emacs packages. You can provide yourself with
 an incremental reading facility by using 'org-capture' alongside a package that
-allows you to browse web pages in emacs -- e.g. w3 or [[http://www.emacswiki.org/emacs/emacs-w3m][emacs-w3m]]. There is a
-large variety of bookmarking packages for emacs which allow you to save your
-place in webpages (another important component of incremental reading). See the
-[[http://www.emacswiki.org/emacs/BookMarks][Emacs Wiki]] for details.
+allows you to browse web pages either in emacs (w3 or [[http://www.emacswiki.org/emacs/emacs-w3m][emacs-w3m]]) or in the
+external browser of your choice ([[http://orgmode.org/worg/org-contrib/org-protocol.php][org-protocol]]).
+
+Another important component of incremental reading is the ability to save your
+exact place in a document, so you can read it /incrementally/ rather than all
+at once. There is a large variety of bookmarking packages for emacs which
+provide advanced bookmarking functionality: see the [[http://www.emacswiki.org/emacs/BookMarks][Emacs Wiki]] for details.
+Bookmarking exact webpage locations in an external browser is a bit more
+difficult. For Firefox, the addon works well.
 
 An example of using Org-Drill for incremental reading is given below. First,
-and most importantly, we need to define an =org-capture= template for captured
-facts:
+and most importantly, we need to define a couple of =org-capture= templates for
+captured facts. 
 
-#+BEGIN_SRC emacs-lisp 
+#+BEGIN_EXAMPLE
 (setq org-capture-templates
-      `(("f" "Fact" entry
-         (file+headline "my_new_facts.org" "Incoming")
-         (concat "* Fact #%(format \"%s\" (float-time))        :"
-                 org-drill-question-tag
-                 ":%^g\n
-    :PROPERTIES:
-    :DATE_ADDED: %t
-    :SOURCE_URL: %a
-    :END:\n
-%i%?\n\n")
+       `(("u"
+         "Task: Read this URL"
+         entry
+         (file+headline "tasks.org" "Articles To Read")
+         ,(concat "* TODO Read article: '%:description'\nURL: %c\n\n")
          :empty-lines 1
-         :immediate-finish nil)
+         :immediate-finish t)
+
+        ("w"
+         "Capture web snippet"
+         entry
+         (file+headline "my-facts.org" "Inbox")
+         ,(concat "* Fact: '%:description'        :"
+                  (format "%s" org-drill-question-tag)
+                  ":\n:PROPERTIES:\n:DATE_ADDED: %u\n:SOURCE_URL: %c\n:END:\n\n%i\n%?\n")
+         :empty-lines 1
+         :immediate-finish t)
         ;; ...other capture templates...
     ))
-#+END_SRC
+#+END_EXAMPLE
 
-Using this template, you can select a region of text which contains a fact you
-want to remember, for example while reading a web page. You then invoke the
-capture template above, and the selected text will be turned into a new fact
-and saved to whichever file and heading you nominate in the template. You will
-be given the opportunity to edit the fact -- you should make sure that the fact
-makes sense independent of its context, as that is how it will be presented to
-you. The easiest way to turn the text into a 'question' is by cloze
-deletion. All you need to do is surround the 'hidden' parts of the text with
-square brackets. 
+Using these templates and =org-protocol=, you can set up buttons in your web
+browser to:
+- Create a task telling you to read the URL of the currently viewed webpage
+- Turn a region of selected text on a webpage, into a new fact which is saved
+  to whichever file and heading you nominate in the template. The fact will
+  contain a timestamp, and a hyperlink back to the webpage where you created
+  it.
 
-Next, you start reading a web page within Emacs. For example, suppose you are
-reading the Wikipedia entry on tuberculosis [[http://en.wikipedia.org/wiki/Tuberculosis][here]].
+For example, suppose you are reading the Wikipedia entry on tuberculosis [[http://en.wikipedia.org/wiki/Tuberculosis][here]].
 
 You read the following:
 
 #+END_QUOTE
 
 You decide you want to remember that "Bacillus Calmette-Guérin vaccine" is the
-name of the vaccine against tuberculosis. First, you select the relevant
-portion of the text as the active region:
+name of the vaccine against tuberculosis. First, you select the `interesting'
+portion of the text with the mouse:
 
 #+BEGIN_QUOTE
 The classic symptoms of tuberculosis are a chronic cough with blood-tinged
 vaccine.@</font>
 #+END_QUOTE
 
-Then you press a key to "capture" this piece of text (whatever key you have
-bound to =org-capture=), followed by "f" to use the "Fact" template shown
-above. 
+Then you press the button you created when setting up =org=protocol=, which is
+configured to activate the capture template "w: Capture web snippet". The
+selected text will be sent to Emacs, turned into a new fact using the template,
+and filed away for your later attention.
 
-A temporary buffer will be created, containing something like:
+(Note that it might be more efficient to turn the entire paragraph into a drill
+item -- since it contains several important facts -- then split it up into
+multiple items when you edit it later in Emacs.)
+
+Once you have had enough of reading the article, save your place, then go to
+your "fact" file in Emacs. You should see that all the pieces of text you
+selected have been turned into drill items. Continuing the above example, you
+would see something like:
 
 #+BEGIN_EXAMPLE
-** Fact #1282372386.671655                           :drill:
-
-    :PROPERTIES:
-    :DATE_ADDED: <2010-08-21 Sat>
-    :SOURCE_URL: [[http://en.wikipedia.org/wiki/Tuberculosis][Tuberculosis - Wikipedia, the free encyclopedia]]
-    :END:
+** Fact: 'Tuberculosis - Wikipedia, the Free Encyclopedia'        :drill:
 
 Prevention relies on screening programs and vaccination, usually with Bacillus
 Calmette-Guérin vaccine.
 #+END_EXAMPLE
 
-Note that the fact's properties automatically contain the date of its creation,
-and a URL linking back to the origin of the fact -- the web page you were
-browsing, in this case. Because fact "titles" are seldom necessary, the title
-of the fact contains a meaningless but unique number (the number of seconds
-elapsed since 1/1/1970).
-
-Next, you edit the sentence so that it makes sense when you are presented with
-it out of context, and you also mark the key fact you want to remember by
-surrounding it with single square brackets.
+You need to edit this fact so it makes sense independent of its context, as
+that is how it will be presented to you in future. The easiest way to turn the
+text into a 'question' is by cloze deletion. All you need to do is surround the
+'hidden' parts of the text with square brackets.
 
 : Prevention of tuberculosis relies on screening programs and vaccination,
 : usually with [Bacillus Calmette-Guérin vaccine].
 
-You then press =C-c C-c=, and the new fact is saved. You continue reading the
-web page, adding other facts if you wish.
 
-Points to note:
-- You can of course define several different "fact" templates, each of which
-  might send its fact to a different file or subheading, or give it different
-  tags or properties, for example.
-- You don't have to use a web browser within Emacs. The "fact" template above
-  will work if you do not have text selected -- the new fact will be empty. You
-  could read a web page (or PDF document, etc) in a program of your choice,
-  copy some text to the clipboard, then switch to Emacs and paste it into a new
-  empty fact.
-- Alternatively, you could define a template that takes its text from the
-  clipboard rather than from the selected region. You can do this by changing
-  the =%i= in the fact template to =%x= or =%^C=. See the documentation for the
-  variable =org-capture-templates= for more details.
+You can of course define browser buttons that use several different "fact"
+templates, each of which might send its fact to a different file or subheading,
+or give it different tags or properties, for example. 
 
 
 * Still to do
 
-
-- hide drawers.
+- hide drawers!
 - =org-drill-question-tag= should use a tag match string, rather than a
   single tag
 - progress indicator during drill session: cumulative time, time spent thinking
   about this card
 - perhaps take account of item priorities, showing high priority items first
-
   :type '(choice integer (const nil)))
 
 
+(defcustom org-drill-failure-quality
+  2
+  "If the quality of recall for an item is this number or lower,
+it is regarded as an unambiguous failure, and the repetition
+interval for the card is reset to 0 days.  By default this is
+2. For Mnemosyne-like behaviour, set it to 1.  Other values are
+not really sensible."
+  :group 'org-drill
+  :type '(choice (const 2) (const 1)))
+
+
 (defcustom org-drill-leech-failure-threshold
   15
   "If an item is forgotten more than this many times, it is tagged
   :type 'boolean)
 
 
-
 (defface org-drill-hidden-cloze-face
-  '((t (:foreground "blue" :background "blue")))
+  '((t (:foreground "deep sky blue" :background "blue")))
   "The face used to hide the contents of cloze phrases."
   :group 'org-drill)
 
 
+(setplist 'org-drill-cloze-overlay-defaults
+          '(display "[...]"
+                    face org-drill-hidden-cloze-face
+                    window t))
+
+
 (defvar org-drill-cloze-regexp
-  ;; old "[^][]\\(\\[[^][][^]]*\\]\\)"
-  "\\(\\[.*?\\]\\|^[^[[:cntrl:]]*?\\]\\|\\[.*?$\\)")
+  ;; ver 1   "[^][]\\(\\[[^][][^]]*\\]\\)"
+  ;; ver 2   "\\(\\[.*?\\]\\|^[^[[:cntrl:]]*?\\]\\|\\[.*?$\\)"
+  "\\(\\[.*?\\]\\|\\[.*?[[:cntrl:]]+.*?\\]\\)")
 
 
 (defcustom org-drill-card-type-alist
   :type '(alist :key-type (choice string (const nil)) :value-type function))
 
 
+(defcustom org-drill-spaced-repetition-algorithm
+  'sm5
+  "Which SuperMemo spaced repetition algorithm to use for scheduling items.
+Available choices are SM2 and SM5."
+  :group 'org-drill
+  :type '(choice (const 'sm2) (const 'sm5)))
+
+(defcustom org-drill-add-random-noise-to-intervals-p
+  nil
+  "If true, the number of days until an item's next repetition
+will vary slightly from the interval calculated by the SM2
+algorithm. The variation is very small when the interval is
+small, and scales up with the interval. The code for calculating
+random noise is adapted from Mnemosyne."
+  :group 'org-drill
+  :type 'boolean)
+
+
 (defvar *org-drill-done-entry-count* 0)
 (defvar *org-drill-pending-entry-count* 0)
 (defvar *org-drill-session-qualities* nil)
       (member org-drill-question-tag (org-get-local-tags))))
 
 
+(defun org-part-of-drill-entry-p ()
+  "Is the current entry either the main heading of a 'drill item',
+or a subheading within a drill item?"
+  (or (org-drill-entry-p)
+      ;; Does this heading INHERIT the drill tag
+      (member org-drill-question-tag (org-get-tags-at))))
+
+
 (defun org-drill-entry-leech-p ()
   "Is the current entry a 'leech item'?"
   (and (org-drill-entry-p)
       nil)))
 
 
+;;; SM2 Algorithm =============================================================
+
+
+(defun determine-next-interval-sm2 (last-interval n ef quality of-matrix)
+  "Arguments:
+- LAST-INTERVAL -- the number of days since the item was last reviewed.
+- N -- the number of times the item has been successfully reviewed
+- EF -- the 'easiness factor'
+- QUALITY -- 0 to 5
+- OF-MATRIX -- a matrix of values, used by SM5 but not by SM2.
+
+Returns a list: (INTERVAL N EF OFMATRIX), where:
+- INTERVAL is the number of days until the item should next be reviewed
+- N is incremented by 1.
+- EF is modified based on the recall quality for the item.
+- OF-MATRIX is not modified."
+  (assert (> n 0))
+  (assert (and (>= quality 0) (<= quality 5)))
+  (if (<= quality org-drill-failure-quality)
+      ;; When an item is failed, its interval is reset to 0,
+      ;; but its EF is unchanged
+      (list -1 1 ef of-matrix)
+    ;; else:
+    (let* ((next-ef (modify-e-factor ef quality))
+           (interval
+            (cond
+             ((<= n 1) 1)
+             ((= n 2)
+              (cond
+               (org-drill-add-random-noise-to-intervals-p
+                (case quality
+                  (5 6)
+                  (4 4)
+                  (3 3)
+                  (2 1)
+                  (t -1)))
+               (t 6)))
+             (t (ceiling (* last-interval next-ef))))))
+      (list (round
+             (if org-drill-add-random-noise-to-intervals-p
+                 (+ last-interval (* (- interval last-interval)
+                                     (org-drill-random-dispersal-factor)))
+               interval))
+            (1+ n) next-ef of-matrix))))
+
+
+;;; SM5 Algorithm =============================================================
+
+;;; From http://www.supermemo.com/english/ol/sm5.htm
+(defun org-drill-random-dispersal-factor ()
+  (let ((a 0.047)
+        (b 0.092)
+        (p (- (random* 1.0) 0.5)))
+    (flet ((sign (n)
+                 (cond ((zerop n) 0)
+                       ((plusp n) 1)
+                       (t -1))))
+      (/ (+ 100 (* (* (/ -1 b) (log (- 1 (* (/ b a ) (abs p)))))
+                   (sign p)))
+         100))))
+      
+
+(defun inter-repetition-interval-sm5 (last-interval n ef &optional of-matrix)
+  (let ((of (get-optimal-factor n ef of-matrix)))
+    (if (= 1 n)
+	of
+      (* of last-interval))))
+
+
+(defun determine-next-interval-sm5 (last-interval n ef quality of-matrix)
+  (assert (> n 0))
+  (assert (and (>= quality 0) (<= quality 5)))
+  (let ((next-ef (modify-e-factor ef quality))
+        (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)
+    
+    (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
+     ;; For a zero-based quality of 4 or 5, don't repeat
+     ((and (>= quality 4)
+           (not org-learn-always-reschedule))
+      (list 0 (1+ n) ef of-matrix))     ; 0 interval = unschedule
+     (t
+      (setq interval (inter-repetition-interval-sm5
+                      last-interval n ef of-matrix))
+      (if org-drill-add-random-noise-to-intervals-p
+          (setq interval (+ last-interval
+                            (* (- interval last-interval)
+                               (org-drill-random-dispersal-factor)))))
+      (list (round interval) (1+ n) ef of-matrix)))))
+
+
+;;; 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)? ")
+  (let* ((learn-str (org-entry-get (point) "LEARN_DATA"))
+	 (learn-data (or (and learn-str
+			      (read learn-str))
+			 (copy-list initial-repetition-state)))
+	 closed-dates)
+    (setq learn-data
+          (case org-drill-spaced-repetition-algorithm
+            (sm5 (determine-next-interval-sm5 (nth 0 learn-data)
+                                              (nth 1 learn-data)
+                                              (nth 2 learn-data)
+                                              quality
+                                              (nth 3 learn-data)))
+            (sm2 (determine-next-interval-sm2 (nth 0 learn-data)
+                                              (nth 1 learn-data)
+                                              (nth 2 learn-data)
+                                              quality
+                                              (nth 3 learn-data)))))
+    (org-entry-put (point) "LEARN_DATA" (prin1-to-string learn-data))
+    (cond
+     ((= 0 (nth 0 learn-data))
+      (org-schedule t))
+     (t
+      (org-schedule nil (time-add (current-time)
+				  (days-to-time (nth 0 learn-data))))))))
+
 
 (defun org-drill-reschedule ()
   "Returns quality rating (0-5), or nil if the user quit."
       (let ((quality (- ch ?0))
             (failures (cdr (assoc "DRILL_FAILURE_COUNT" (org-entry-properties nil)))))
         (save-excursion
-          (org-smart-reschedule quality))
+          (org-drill-smart-reschedule quality))
         (push quality *org-drill-session-qualities*)
         (cond
-         ((< quality 3)
+         ((<= quality org-drill-failure-quality)
           (when org-drill-leech-failure-threshold
             (setq failures (if failures (string-to-number failures) 0))
             (org-set-property "DRILL_FAILURE_COUNT"
       (otherwise t))))
 
 
+(defun org-drill-hide-clozed-text ()
+  (let ((ovl nil))
+    (save-excursion
+      (while (re-search-forward org-drill-cloze-regexp nil t)
+        (setf ovl (make-overlay (match-beginning 0) (match-end 0)))
+        (overlay-put ovl 'category
+                     'org-drill-cloze-overlay-defaults)
+        (when (find ?| (match-string 0))
+          (overlay-put ovl
+                       'display
+                       (format "[...%s]"
+                               (substring-no-properties
+                                (match-string 0)
+                                (1+ (position ?| (match-string 0)))
+                                (1- (length (match-string 0)))))))))))
+
+
+(defun org-drill-unhide-clozed-text ()
+  (save-excursion
+    (dolist (ovl (overlays-in (point-min) (point-max)))
+      (when (eql 'org-drill-cloze-overlay-defaults (overlay-get ovl 'category))
+        (delete-overlay ovl)))))
+
+
+
 ;;; Presentation functions ====================================================
 
 ;; Each of these is called with point on topic heading.  Each needs to show the
       (let ((presentation-fn (cdr (assoc card-type org-drill-card-type-alist))))
         (cond
          (presentation-fn
-          (highlight-regexp org-drill-cloze-regexp
-                            'org-drill-hidden-cloze-face)
-          (setq cont (funcall presentation-fn))
-          (unhighlight-regexp org-drill-cloze-regexp))
+          (org-drill-hide-clozed-text)
+          ;;(highlight-regexp org-drill-cloze-regexp
+          ;;                  'org-drill-hidden-cloze-face)
+          (unwind-protect
+              (progn
+                (setq cont (funcall presentation-fn)))
+            (org-drill-unhide-clozed-text))
+          ;;(unhighlight-regexp org-drill-cloze-regexp)
+          )
          (t
           (error "Unknown card type: '%s'" card-type))))
       
           (org-drill-reschedule)))))))
 
 
-
 (defun org-drill-entries (entries)
   "Returns nil, t, or a list of markers representing entries that were
 'failed' and need to be presented again before the session ends."
  (format-seconds "%h:%.2m:%.2s"
                  (- (float-time (current-time)) *org-drill-start-time*))
  (round (* 100 (count 5 *org-drill-session-qualities*))
-        (length *org-drill-session-qualities*))
+        (max 1 (length *org-drill-session-qualities*)))
  (round (* 100 (count 4 *org-drill-session-qualities*))
-        (length *org-drill-session-qualities*))
+        (max 1 (length *org-drill-session-qualities*)))
  (round (* 100 (count 3 *org-drill-session-qualities*))
-        (length *org-drill-session-qualities*))
+        (max 1 (length *org-drill-session-qualities*)))
  (round (* 100 (count 2 *org-drill-session-qualities*))
-        (length *org-drill-session-qualities*))
+        (max 1 (length *org-drill-session-qualities*)))
  (round (* 100 (count 1 *org-drill-session-qualities*))
-        (length *org-drill-session-qualities*))
+        (max 1 (length *org-drill-session-qualities*)))
  (round (* 100 (count 0 *org-drill-session-qualities*))
-        (length *org-drill-session-qualities*))
+        (max 1 (length *org-drill-session-qualities*)))
  )))
 
 
                  (cond
                   ((org-drill-entry-new-p)
                    (push (point-marker) new-entries))
-                  ((member (org-drill-entry-last-quality) '(0 1 2))
+                  ((<= (org-drill-entry-last-quality)
+                       org-drill-failure-quality)
                    (push (point-marker) failed-entries))
                   (t
                    (push (point-marker) old-entries)))))
 # cloze deletion of test in [square brackets], without the need to hide any
 # subtopics (though they WILL still be hidden if present).
 
+# If the text between the brackets contains a `|' character, everything after
+# that character is considered to be a `hint', and will remain visible when the
+# rest of the clozed text is hidden.
+
 # Set the variable `org-drill-use-visible-cloze-face-p' to `t' if you want 
 # cloze-deleted text to be shown in a special face when you are editing org
 # mode buffers.
 
 *** Grammar Rule                                     :drill:
 
-To form an adverb from an adjective, add [-mente] to the [feminine] (gender)
+To form an adverb from an adjective, add [-mente] to the [feminine|gender] 
 form of the adjective.
 
 ** Vocabulary
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.