Commits

eeeickythump  committed 16cafa2

Many changes:
- Item drill data is stored in a clearer format, each value has its own property, the old 'org-learn'
LEARN_DATA property has been dropped. Items that contain LEARN_DATA are silently rolled over to
the new format.
- For SM5, matrix of optimal factors is now correctly *global* rather than per-item, and is saved
between drill sessions as an emacs customization variable.
- We store interval data as floating point numbers rather than rounding to the nearest integer.
- New experimental algorithm: 'simple8', based on SuperMemo SM8.
- New options:
- org-drill-forgetting-index: define the percentage of items that it is "acceptable" to fail.
A warning message is shown after the drill session if more items than this were failed.
- org-drill-learn-fraction: governs how fast time intervals increase with each successful
repetition of an item.
- org-drill-adjust-intervals-for-early-and-late-repetitions-p: if true, alter next scheduled date
if an item is reviewed earlier or later than it was supposed to be.
- Almost all variables have been declared safe for file-local reassignment.
- We now ignore org-learn-always-reschedule, regarding it as always true.
- Post-session report now shows a count of dormant items (those not yet due for review).

  • Participants
  • Parent commits 30be932
  • Tags 2.0

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-04-04 10:18:44 "/>
+<meta name="generated" content="2011-04-08 16:00:36 "/>
 <meta name="author" content="Paul Sexton"/>
 <meta name="description" content=""/>
 <meta name="keywords" content=""/>
 <div id="text-table-of-contents">
 <ul>
 <li><a href="#sec-1">Synopsis </a></li>
-<li><a href="#sec-2">Installation and Customisation </a></li>
+<li><a href="#sec-2">Installation </a></li>
 <li><a href="#sec-3">Demonstration </a></li>
 <li><a href="#sec-4">Writing the questions </a>
 <ul>
 <li><a href="#sec-4_3">Two-sided cards </a></li>
 <li><a href="#sec-4_4">Multi-sided cards </a></li>
 <li><a href="#sec-4_5">Multi-cloze cards </a></li>
-<li><a href="#sec-4_6">User-defined topic types </a></li>
-<li><a href="#sec-4_7">Comments </a></li>
+<li><a href="#sec-4_6">User-defined card types </a></li>
 </ul>
 </li>
 <li><a href="#sec-5">Running the drill session </a></li>
-<li><a href="#sec-6">Leeches </a></li>
-<li><a href="#sec-7">Cram mode </a></li>
-<li><a href="#sec-8">Incremental reading </a></li>
-<li><a href="#sec-9">Still to do </a></li>
+<li><a href="#sec-6">Cram mode </a></li>
+<li><a href="#sec-7">Leeches </a></li>
+<li><a href="#sec-8">Customisation </a>
+<ul>
+<li><a href="#sec-8_1">Appearance of items during drill sessions </a></li>
+<li><a href="#sec-8_2">Duration of drill sessions </a></li>
+<li><a href="#sec-8_3">Spaced repetition algorithm </a>
+<ul>
+<li><a href="#sec-8_3_1">Choice of algorithm </a></li>
+<li><a href="#sec-8_3_2">Random variation of repetition intervals </a></li>
+<li><a href="#sec-8_3_3">Adjustment for early or late review of items </a></li>
+<li><a href="#sec-8_3_4">Adjusting item difficulty globally </a></li>
+</ul>
+</li>
+<li><a href="#sec-8_4">Per-file customisation settings </a></li>
+</ul>
+</li>
+<li><a href="#sec-9">Incremental reading </a></li>
 </ul>
 </div>
 </div>
 that use it, see:
 </p><ul>
 <li>
-<a href="http://supermemo.com/index.htm">SuperMemo</a> (the SM5 algorithm is discussed <a href="http://www.supermemo.com/english/ol/sm5.htm">here</a>)
+<a href="http://supermemo.com/index.htm">SuperMemo</a> (see descriptions of the SM2, SM5 and SM8 algorithms)
 </li>
 <li>
 <a href="http://ichi2.net/anki/">Anki</a>
 </div>
 
 <div id="outline-container-2" class="outline-2">
-<h2 id="sec-2">Installation and Customisation </h2>
+<h2 id="sec-2">Installation </h2>
 <div class="outline-text-2" id="text-2">
 
 
 
 
 
-<p>
-I also recommend the following, so that items are always eventually retested,
-even when you remember them well.
-</p>
-
-
-
-<pre class="example">(setq org-learn-always-reschedule t)
-</pre>
-
-
-
-<p>
-If you want cloze-deleted text to show up in a special font within Org mode
-buffers, also add:
-</p>
-
-
-
-<pre class="example">(setq org-drill-use-visible-cloze-face-p t)
-</pre>
-
-
-
-<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
-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>
-
-
 
 
 </div>
 
 <p>
 Org-Drill uses org mode topics as 'drill items'. To be used as a drill item,
-the topic must have a tag that matches <code>org-drill-question-tag</code>. This is
-<code>:drill:</code> by default. Any other org topics will be ignored.
+the topic must have a tag that matches the value of
+<code>org-drill-question-tag</code>. This is <code>:drill:</code> by default. Any other org topics
+will be ignored.
 </p>
 <p>
 You don't need to schedule the topics initially.  However <code>org-drill</code> <b>will</b>
 </p>
 <p>
 How should 'drill topics' be structured? Any org topic is a legal drill topic
-&ndash; it will simply be shown with subheadings collapsed. After pressing a
-key, any hidden subheadings will be revealed, and you will be asked to rate
-your "recall" of the item.
+&ndash; it will simply be shown with all subheadings collapsed, so thta only the
+material beneath the main item heading is visible. After pressing a key, any
+hidden subheadings will be revealed, and you will be asked to rate your
+"recall" of the item.
 </p>
 <p>
 This will be adequate for some items, but usually you will want to write items
 where you have more control over what information is hidden from the user for
-recall purposes.
+recall purposes. For this reason, some other card types are defined, including:
+</p><ul>
+<li>
+<a href="#sec-4_3">Two-sided cards</a>
+</li>
+<li>
+<a href="#sec-4_4">Multi-sided cards</a>
+</li>
+<li>
+<a href="#Multicloze--cards">Multicloze cards</a>
+</li>
+<li>
+<a href="#sec-4_6">User-defined card types</a>
+</li>
+</ul>
+
+
+<p>
+<b>A note about comments:</b> 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, comments are always rendered
+invisible while items are being tested.
 </p>
 
+
 </div>
 
 <div id="outline-container-4_1" class="outline-3">
 <div class="outline-text-3" id="text-4_1">
 
 
+
 <p>
 The simplest drill topic has no special structure. When such a topic is
 presented during a drill session, any subheadings are "collapsed" with their
 
 
 
-<pre class="example">* Item                                   :drill:
-What is the capital city of Estonia?
+<pre class="src src-org"><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Item                                   </span><span style="color: #66cdaa; background-color: #4169e1; font-weight: bold;">:drill:</span><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">
+</span>What is the capital city of Estonia?
 
-** The Answer
-Tallinn.
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** The Answer
+</span>Tallinn.
 </pre>
 
 
 <div class="outline-text-3" id="text-4_2">
 
 
+
 <p>
 Cloze deletion can be used in any drill topic regardless of whether it is
 otherwise 'simple', or is one of the specialised topic types discussed
 
 
 
-<pre class="example">* Item                                   :drill:
-The capital city of Estonia is [Tallinn].
+
+<pre class="src src-org"><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Item                                   </span><span style="color: #66cdaa; background-color: #4169e1; font-weight: bold;">:drill:</span><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">
+</span>The capital city of Estonia is <span style="color: #ab82ff;">[Tallinn]</span>.
 </pre>
 
 
 
 
 
-<pre class="example">Type 1 hypersensitivity reactions are mediated by [immunoglobulin E|molecule]
-and [mast cells|cell type].
+<pre class="src src-org">Type 1 hypersensitivity reactions are mediated by <span style="color: #ab82ff;">[immunoglobulin E</span><span style="color: #483d8b;">|molecule</span><span style="color: #ab82ff;">]</span>
+and <span style="color: #ab82ff;">[mast cells</span><span style="color: #483d8b;">|cell type</span><span style="color: #ab82ff;">]</span>.
 </pre>
 
 
 </div>
 
 <div id="outline-container-4_3" class="outline-3">
-<h3 id="sec-4_3">Two-sided cards </h3>
+<h3 id="sec-4_3"><a name="Two-sided--cards" id="Two-sided--cards"></a>Two-sided cards </h3>
 <div class="outline-text-3" id="text-4_3">
 
 
 
 
 
-<pre class="example">* Noun                                               :drill:
-    :PROPERTIES:
-    :DRILL_CARD_TYPE: twosided
-    :END:
+<pre class="src src-org"><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Noun                                               </span><span style="color: #66cdaa; background-color: #4169e1; font-weight: bold;">:drill:</span><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">
+</span><span style="color: #8b4789;">    :PROPERTIES:</span>
+    <span style="color: #8b4789;">:DRILL_CARD_TYPE:</span> <span style="color: #006400;">twosided</span>
+<span style="color: #8b4789;">    :END:</span>
 
 Translate this word.
 
-** Spanish
-la mujer
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** Spanish
+</span>la mujer
 
-** English
-the woman
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** English
+</span>the woman
 
-** Example sentence
-¿Quién fue esa mujer?
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** Example sentence
+</span>&#191;Qui&#233;n fue esa mujer?
 Who was that woman?
 </pre>
 
 </div>
 
 <div id="outline-container-4_4" class="outline-3">
-<h3 id="sec-4_4">Multi-sided cards </h3>
+<h3 id="sec-4_4"><a name="Multi-sided--cards" id="Multi-sided--cards"></a>Multi-sided cards </h3>
 <div class="outline-text-3" id="text-4_4">
 
 
+
 <p>
 The <code>multisided</code> card type is similar to <code>twosided</code>, except that any
 subheading has a chance of being presented during the topic review. One
 
 
 
-<pre class="example">* Noun                                               :drill:
-    :PROPERTIES:
-    :DRILL_CARD_TYPE: multisided
-    :END:
+<pre class="src src-org"><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Noun                                               </span><span style="color: #66cdaa; background-color: #4169e1; font-weight: bold;">:drill:</span><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">
+</span><span style="color: #8b4789;">    :PROPERTIES:</span>
+    <span style="color: #8b4789;">:DRILL_CARD_TYPE:</span> <span style="color: #006400;">multisided</span>
+<span style="color: #8b4789;">    :END:</span>
 
 Translate.
 
-** Spanish
-la mesa
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** Spanish
+</span>la mesa
 
-** English
-the table
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** English
+</span>the table
 
-** Picture
-[[file:table.jpg][PICTURE]]
+<span style="color: #4876ff; background-color: #000080; font-weight: bold;">** Picture
+</span><span style="color: #00bfff; text-decoration: underline;">PICTURE</span>
 </pre>
 
 
 The user will be shown the main text and either 'la mujer', <i>or</i> 'the woman',
 <i>or</i> a picture of a table.
 </p>
+
 </div>
 
 </div>
 
 <div id="outline-container-4_5" class="outline-3">
-<h3 id="sec-4_5">Multi-cloze cards </h3>
+<h3 id="sec-4_5"><a name="Multi-cloze--cards" id="Multi-cloze--cards"></a>Multi-cloze cards </h3>
 <div class="outline-text-3" id="text-4_5">
 
 
+
 <p>
 Often, you will wish to create cards out of sentences that express several
 facts, such as the following:
 </p>
-<blockquote>
 
-<p>The capital city of New Zealand is Wellington, which is located in the
+
+
+<pre class="src src-org">The capital city of New Zealand is Wellington, which is located in the
 South Island and has a population of about 400,000.
-</p>
-</blockquote>
+</pre>
+
 
 
 <p>
 There is more than one fact in this statement &ndash; you could create a single
 'simple' card with all the facts marked as cloze text, like so:
 </p>
-<blockquote>
 
-<p>The capital city of [New Zealand] is [Wellington], which is located in
-[the South Island] and has a population of about [400,000].
-</p>
-</blockquote>
+
+
+<pre class="src src-org">The capital city of <span style="color: #ab82ff;">[New Zealand]</span> is <span style="color: #ab82ff;">[Wellington]</span>, which is located in
+the <span style="color: #ab82ff;">[North</span><span style="color: #483d8b;">|North/South</span><span style="color: #ab82ff;">]</span> Island and has a population of about <span style="color: #ab82ff;">[400,000]</span>.
+</pre>
+
 
 
 <p>
 But this card will be difficult to remember. If you get just one of the 4
 hidden facts wrong, you will fail the card. A card like this is likely to
-become a <a href="#sec-6">leech</a>.
+become a <a href="#sec-7">leech</a>.
 </p>
 <p>
 A better way to express all these facts using 'simple' cards is to create
 
 
 
-<pre class="example">* Fact
-The capital city of [New Zealand] is Wellington, which has a population of
+<pre class="src src-org"><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span>The capital city of <span style="color: #ab82ff;">[New Zealand]</span> is Wellington, which has a population of
 about 400,000.
 
-* Fact
-The capital city of New Zealand is [Wellington], which has a population of
+<span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span>The capital city of New Zealand is <span style="color: #ab82ff;">[Wellington]</span>, which has a population of
 about 400,000.
 
-* Fact
-The capital city of New Zealand is Wellington, which has a population of
-about [400,000].
+<span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span>The capital city of New Zealand is Wellington, which has a population of
+about <span style="color: #ab82ff;">[400,000]</span>.
 
-* Fact
-The capital city of [New Zealand] is Wellington, which is located in the
-the South Island.
+<span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span>The capital city of <span style="color: #ab82ff;">[New Zealand]</span> is Wellington, which is located in the
+the North Island.
 
-* Fact
-The capital city of New Zealand is [Wellington], which is located in
-the South Island.
+<span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span>The capital city of New Zealand is <span style="color: #ab82ff;">[Wellington]</span>, which is located in
+the North Island.
 
-* Fact
-The capital city of New Zealand is Wellington, which is located in
-[the South Island].
+<span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span>The capital city of New Zealand is Wellington, which is located in
+the <span style="color: #ab82ff;">[North</span><span style="color: #483d8b;">|North/South</span><span style="color: #ab82ff;">]</span> Island.
 </pre>
 
 
 
 
 
-<pre class="example">* Fact
-  :PROPERTIES:
-  :DRILL_CARD_TYPE: multicloze
-  :END:
+<pre class="src src-org"><span style="color: #f0ffff; background-color: #4169e1; font-weight: bold;">* Fact
+</span><span style="color: #8b4789;">  :PROPERTIES:</span>
+  <span style="color: #8b4789;">:DRILL_CARD_TYPE:</span> <span style="color: #006400;">multicloze</span>
+<span style="color: #8b4789;">  :END:</span>
 
-The capital city of [New Zealand] is [Wellington], which is located in
-[the South Island] and has a population of about [400,000].
+The capital city of <span style="color: #ab82ff;">[New Zealand]</span> is <span style="color: #ab82ff;">[Wellington]</span>, which is located in
+the <span style="color: #ab82ff;">[North</span><span style="color: #483d8b;">|North/South</span><span style="color: #ab82ff;">]</span> Island and has a population of about <span style="color: #ab82ff;">[400,000]</span>.
 </pre>
 
 
 
+
 </div>
 
 </div>
 
 <div id="outline-container-4_6" class="outline-3">
-<h3 id="sec-4_6">User-defined topic types </h3>
+<h3 id="sec-4_6"><a name="User-defined--card--types" id="User-defined--card--types"></a>User-defined card types </h3>
 <div class="outline-text-3" id="text-4_6">
 
 
+
 <p>
-Finally, you can write your own elisp functions to define new kinds of
+Finally, you can write your own emacs lisp functions to define new kinds of
 topics. Any new topic type will need to be added to
 <code>org-drill-card-type-alist</code>, and cards using that topic type will need to have
 it as the value of their <code>DRILL_CARD_TYPE</code> property. For an example, see the
 <p>
 See the file <a href="spanish.html">spanish.org</a> for a full set of example material.
 </p>
-</div>
 
-</div>
-
-<div id="outline-container-4_7" class="outline-3">
-<h3 id="sec-4_7">Comments </h3>
-<div class="outline-text-3" id="text-4_7">
-
-
-<p>
-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, comments are always rendered invisible while items are
-being tested.
-</p>
 
 </div>
 </div>
 </div>
 
 <div id="outline-container-6" class="outline-2">
-<h2 id="sec-6"><a name="leeches" id="leeches"></a>Leeches </h2>
+<h2 id="sec-6">Cram mode </h2>
 <div class="outline-text-2" id="text-6">
 
 
+
+<p>
+There are some situations, such as before an exam, where you will want to
+revise all of your cards regardless of when they are next due for review.
+</p>
+<p>
+To do this, run a <i>cram session</i> with the <code>org-drill-cram</code> command (<code>M-x org-drill-cram RET</code>). This works the same as a normal drill session, except
+that all items are considered due for review unless you reviewed them within
+the last 12 hours (you can change the number of hours by customising the
+variable <code>org-drill-cram-hours</code>).
+</p>
+
+</div>
+
+</div>
+
+<div id="outline-container-7" class="outline-2">
+<h2 id="sec-7"><a name="leeches" id="leeches"></a>Leeches </h2>
+<div class="outline-text-2" id="text-7">
+
+
 <p>
 From the Anki website, <a href="http://ichi2.net/anki/wiki/Leeches">http://ichi2.net/anki/wiki/Leeches</a>:
 </p>
 
 </div>
 
-<div id="outline-container-7" class="outline-2">
-<h2 id="sec-7">Cram mode </h2>
-<div class="outline-text-2" id="text-7">
+<div id="outline-container-8" class="outline-2">
+<h2 id="sec-8">Customisation </h2>
+<div class="outline-text-2" id="text-8">
 
 
 
 <p>
-There are some situations, such as before an exam, where you will want to
-revise all of your cards regardless of when they are next due for review.
+Org-Drill has several settings which you change using
+<code>M-x customize-group org-drill &lt;RET&gt;</code>. Alternatively you can change these
+settings by adding elisp code to your configuration file (<code>.emacs</code>).
 </p>
+
+
+</div>
+
+<div id="outline-container-8_1" class="outline-3">
+<h3 id="sec-8_1">Appearance of items during drill sessions </h3>
+<div class="outline-text-3" id="text-8_1">
+
+
+
 <p>
-To do this, run a <i>cram session</i> with the <code>org-drill-cram</code> command (<code>M-x org-drill-cram RET</code>). This works the same as a normal drill session, except
-that all items are considered due for review unless you reviewed them within
-the last 12 hours (you can change the number of hours by customising the
-variable <code>org-drill-cram-hours</code>).
+If you want cloze-deleted text to show up in a special font within Org mode
+buffers, add this to your .emacs:
+</p>
+
+
+
+<pre class="example">(setq org-drill-use-visible-cloze-face-p t)
+</pre>
+
+
+
+<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>
+
+
+
+
+</div>
+
+</div>
+
+<div id="outline-container-8_2" class="outline-3">
+<h3 id="sec-8_2">Duration of drill sessions </h3>
+<div class="outline-text-3" id="text-8_2">
+
+
+
+<p>
+By default, a drill session will end when either 30 items have been
+successfully reviewed, or 20 minutes have passed. To change this behaviour, use
+the following settings.
+</p>
+
+
+
+<pre class="example">(setq org-drill-maximum-items-per-session 40)
+(setq org-drill-maximum-duration 30)   ; 30 minutes
+</pre>
+
+
+
+<p>
+If either of these variables is set to nil, then item count or elapsed time
+will not count as reasons to end the session. If both variables are nil, the
+session will not end until <i>all</i> outstanding items have been reviewed.
 </p>
 
 </div>
 
 </div>
 
-<div id="outline-container-8" class="outline-2">
-<h2 id="sec-8">Incremental reading </h2>
-<div class="outline-text-2" id="text-8">
+<div id="outline-container-8_3" class="outline-3">
+<h3 id="sec-8_3">Spaced repetition algorithm </h3>
+<div class="outline-text-3" id="text-8_3">
+
+
+
+
+</div>
+
+<div id="outline-container-8_3_1" class="outline-4">
+<h4 id="sec-8_3_1">Choice of algorithm </h4>
+<div class="outline-text-4" id="text-8_3_1">
+
+
+
+<p>
+Org-Drill supports three different spaced repetition algorithms, all based on
+SuperMemo algorithms. These are:
+</p><dl>
+<dt><a href="http://www.supermemo.com/english/ol/sm2.htm">SM2</a></dt><dd>
+an early algorithm, used in SuperMemo 2.0 (1988), which remains very
+popular &ndash; Anki and Mnemosyne, two of the most popular spaced repetition
+programs, use SM2. This algorithm stores an 'ease factor' for each item,
+which is modified each time you rate your recall of the item.
+</dd>
+<dt><a href="http://www.supermemo.com/english/ol/sm5.htm">SM5</a> (default)</dt><dd>
+used in SuperMemo 5.0 (1989). This algorithm uses 'ease
+factors' but also uses a persistent, per-user 'matrix of optimal factors'
+which is also modified after each item repetition.
+</dd>
+<dt>Simple8</dt><dd>
+an experimental algorithm based on the <a href="http://www.supermemo.com/english/algsm8.htm">SM8</a> algorithm. SM8 is used
+in SuperMemo 8.0 (1998) and is almost identical to SM11 which is
+used in SuperMemo 2002. Like SM5, it uses a matrix of optimal
+factors. Simple8 differs from SM8 in that it does not adapt the
+matrix to the individual user, though it does adapt each item's
+'ease factor'.
+
+</dd>
+</dl>
+
+
+<p>
+If you want Org-Drill to use the <code>SM2</code> algorithm, put the following in your
+<code>.emacs</code>:
+</p>
+
+
+
+<pre class="example">(setq org-drill-spaced-repetition-algorithm 'sm2)
+</pre>
+
+
+
+
+</div>
+
+</div>
+
+<div id="outline-container-8_3_2" class="outline-4">
+<h4 id="sec-8_3_2">Random variation of repetition intervals </h4>
+<div class="outline-text-4" id="text-8_3_2">
+
+
+
+<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>
+
+
+
+
+</div>
+
+</div>
+
+<div id="outline-container-8_3_3" class="outline-4">
+<h4 id="sec-8_3_3">Adjustment for early or late review of items </h4>
+<div class="outline-text-4" id="text-8_3_3">
+
+
+
+<p>
+Reviewing items earlier or later than their scheduled review date may affect
+how soon the next review date should be scheduled. Code to make this adjustment
+is also presented on the SuperMemo website. It can be enabled with:
+</p>
+
+
+
+<pre class="example">(setq org-drill-adjust-intervals-for-early-and-late-repetitions-p t)
+</pre>
+
+
+
+<p>
+This will affect both early and late repetitions if the Simple8 algorithm is
+used. For the SM5 algorithm it will affect early repetitions only. It has no
+effect on the SM2 algorithm.
+</p>
+
+</div>
+
+</div>
+
+<div id="outline-container-8_3_4" class="outline-4">
+<h4 id="sec-8_3_4">Adjusting item difficulty globally </h4>
+<div class="outline-text-4" id="text-8_3_4">
+
+
+
+<p>
+The <code>learn fraction</code> is a global value which affects how quickly the intervals
+(times between each retest of an item) increase with successive repetitions,
+for <i>all</i> items. The default value is 0.5, and this is the value used in
+SuperMemo. For some collections of information, you may find that you are
+reviewing items too often (they are too easy and the workload is too high), or
+too seldom (you are failing them too often). In these situations, it is
+possible to alter the learn fraction from its default in order to increase or
+decrease the frequency of repetition of items over time. Increasing the value
+will make the time intervals grow faster, and lowering it will make them grow
+more slowly. The table below shows the growth in intervals (in days) with some
+different values of the learn fraction (F). The table assumes that the item is
+successfully recalled each time, with an average quality of just under 4.
+</p>
+
+<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
+<caption></caption>
+<colgroup><col class="left" /><col class="right" /><col class="right" /><col class="right" /><col class="right" /><col class="right" />
+</colgroup>
+<thead>
+<tr><th scope="col" class="left">Repetition</th><th scope="col" class="right">F=0.3</th><th scope="col" class="right">F=0.4</th><th scope="col" class="right"><b>F=0.5</b></th><th scope="col" class="right">F=0.6</th><th scope="col" class="right">F=0.7</th></tr>
+</thead>
+<tbody>
+<tr><td class="left">1st</td><td class="right">2</td><td class="right">2</td><td class="right">2</td><td class="right">2</td><td class="right">2</td></tr>
+<tr><td class="left">2nd</td><td class="right">7</td><td class="right">7</td><td class="right">7</td><td class="right">7</td><td class="right">7</td></tr>
+<tr><td class="left">5th</td><td class="right">26</td><td class="right">34</td><td class="right">46</td><td class="right">63</td><td class="right">85</td></tr>
+<tr><td class="left">10th</td><td class="right">85</td><td class="right">152</td><td class="right">316</td><td class="right">743</td><td class="right">1942</td></tr>
+<tr><td class="left">15th</td><td class="right">233</td><td class="right">501</td><td class="right">1426</td><td class="right">5471</td><td class="right">27868</td></tr>
+</tbody>
+</table>
+
+
+<p>
+To alter the learn fraction, put the following in your .emacs:
+</p>
+
+
+
+<pre class="src src-elisp"><span style="color: #696969;">(</span>setq org-drill-learn-fraction 0.45<span style="color: #696969;">)</span>   <span style="color: #db7093;">; </span><span style="color: #db7093;">change the value as desired
+</span></pre>
+
+
+
+
+</div>
+</div>
+
+</div>
+
+<div id="outline-container-8_4" class="outline-3">
+<h3 id="sec-8_4">Per-file customisation settings </h3>
+<div class="outline-text-3" id="text-8_4">
+
+
+
+<p>
+Most of the above settings are safe as file-local variables. This means you can
+include a commented section like this at the end of your .org file to apply
+special settings when running a Drill session using that file:
+</p>
+
+
+
+<pre class="src src-org"><span style="color: #db7093;"># Local Variables&#58;</span>
+<span style="color: #db7093;"># org-drill-maximum-items-per-session:    50</span>
+<span style="color: #db7093;"># org-drill-spaced-repetition-algorithm:  simple8</span>
+<span style="color: #db7093;"># End:</span>
+</pre>
+
+
+
+
+</div>
+</div>
+
+</div>
+
+<div id="outline-container-9" class="outline-2">
+<h2 id="sec-9">Incremental reading </h2>
+<div class="outline-text-2" id="text-9">
 
 
 
 
 
 
-<pre class="example">(setq org-capture-templates
-       `(("u"
-         "Task: Read this URL"
+<pre class="src src-elisp"><span style="color: #696969;">(</span>setq org-capture-templates
+       `<span style="color: #696969;">((</span><span style="color: #008b00;">"u"</span>
+         <span style="color: #008b00;">"Task: Read this URL"</span>
          entry
-         (file+headline "tasks.org" "Articles To Read")
-         ,(concat "* TODO Read article: '%:description'\nURL: %c\n\n")
-         :empty-lines 1
-         :immediate-finish t)
+         <span style="color: #696969;">(</span>file+headline <span style="color: #008b00;">"tasks.org"</span> <span style="color: #008b00;">"Articles To Read"</span><span style="color: #696969;">)</span>
+         ,<span style="color: #696969;">(</span>concat <span style="color: #008b00;">"* TODO Read article: '%:description'\nURL: %c\n\n"</span><span style="color: #696969;">)</span>
+         <span style="color: #4169e1;">:empty-lines</span> 1
+         <span style="color: #4169e1;">:immediate-finish</span> t<span style="color: #696969;">)</span>
 
-        ("w"
-         "Capture web snippet"
+        <span style="color: #696969;">(</span><span style="color: #008b00;">"w"</span>
+         <span style="color: #008b00;">"Capture web snippet"</span>
          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...
-    ))
+         <span style="color: #696969;">(</span>file+headline <span style="color: #008b00;">"my-facts.org"</span> <span style="color: #008b00;">"Inbox"</span><span style="color: #696969;">)</span>
+         ,<span style="color: #696969;">(</span>concat <span style="color: #008b00;">"* Fact: '%:description'        :"</span>
+                  <span style="color: #696969;">(</span>format <span style="color: #008b00;">"%s"</span> org-drill-question-tag<span style="color: #696969;">)</span>
+                  <span style="color: #008b00;">":\n:PROPERTIES:\n:DATE_ADDED: %u\n:SOURCE_URL: %c\n:END:\n\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> t<span style="color: #696969;">)</span>
+        <span style="color: #db7093;">;; </span><span style="color: #db7093;">...other capture templates...
+</span>    <span style="color: #696969;">))</span>
 </pre>
 
 
 
 
 
-<pre class="example">** Fact: 'Tuberculosis - Wikipedia, the Free Encyclopedia'        :drill:
-
+<pre class="src src-org"><span style="color: #4876ff; background-color: #000080; font-weight: bold;">** Fact: 'Tuberculosis - Wikipedia, the Free Encyclopedia'        </span><span style="color: #66cdaa; background-color: #000080; font-weight: bold;">:drill:</span><span style="color: #4876ff; background-color: #000080; font-weight: bold;">
+</span>
 Prevention relies on screening programs and vaccination, usually with Bacillus
-Calmette-Guérin vaccine.
+Calmette-Gu&#233;rin vaccine.
 </pre>
 
 
 </p>
 
 </div>
-
-</div>
-
-<div id="outline-container-9" class="outline-2">
-<h2 id="sec-9">Still to do </h2>
-<div class="outline-text-2" id="text-9">
-
-
-<ul>
-<li>
-<code>org-drill-question-tag</code> should use a tag match string, rather than a
-single tag? Can use <code>org-make-tag-matcher</code>.
-</li>
-<li>
-perhaps take account of item priorities, showing high priority items first
-</li>
-<li>
-get tooltips to work for old/new/etc counts during review?
-</li>
-</ul>
-
-</div>
 </div>
 <div id="postamble">
 <p class="author"> Author: Paul Sexton
 </p>
-<p class="date"> Date: 2011-04-04 10:18:44 </p>
+<p class="date"> Date: 2011-04-08 16:00:36 </p>
 <p class="creator">HTML generated by org-mode 7.4 in emacs 23</p>
 </div>
 </div>
 
 For more on the spaced repetition algorithm, and examples of other programs
 that use it, see:
-- [[http://supermemo.com/index.htm][SuperMemo]] (the SM5 algorithm is discussed [[http://www.supermemo.com/english/ol/sm5.htm][here]])
+- [[http://supermemo.com/index.htm][SuperMemo]] (see descriptions of the SM2, SM5 and SM8 algorithms)
 - [[http://ichi2.net/anki/][Anki]]
 - [[http://mnemosyne-proj.org/index.php][Mnemosyne]]
 
 
-* Installation and Customisation
+* Installation
 
 
 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_EXAMPLE
+#+BEGIN_SRC elisp
 (require 'org-drill)
-#+END_EXAMPLE
+#+END_SRC
 
-I also recommend the following, so that items are always eventually retested,
-even when you remember them well.
-
-#+BEGIN_EXAMPLE
-(setq org-learn-always-reschedule t)
-#+END_EXAMPLE
-
-If you want cloze-deleted text to show up in a special font within Org mode
-buffers, also add:
-
-#+BEGIN_EXAMPLE
-(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
-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
 
 
 Org-Drill uses org mode topics as 'drill items'. To be used as a drill item,
-the topic must have a tag that matches =org-drill-question-tag=. This is
-=:drill:= by default. Any other org topics will be ignored.
+the topic must have a tag that matches the value of
+=org-drill-question-tag=. This is =:drill:= by default. Any other org topics
+will be ignored.
 
 You don't need to schedule the topics initially.  However =org-drill= *will*
 recognise items that have been scheduled previously with
 memorisation.
 
 How should 'drill topics' be structured? Any org topic is a legal drill topic
--- it will simply be shown with subheadings collapsed. After pressing a
-key, any hidden subheadings will be revealed, and you will be asked to rate
-your "recall" of the item.
+-- it will simply be shown with all subheadings collapsed, so thta only the
+material beneath the main item heading is visible. After pressing a key, any
+hidden subheadings will be revealed, and you will be asked to rate your
+"recall" of the item.
 
 This will be adequate for some items, but usually you will want to write items
 where you have more control over what information is hidden from the user for
-recall purposes.
+recall purposes. For this reason, some other card types are defined, including:
+- [[Two-sided cards]]
+- [[Multi-sided cards]]
+- [[Multicloze cards]]
+- [[User-defined card types]]
+
+*A note about comments:* 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, comments are always rendered
+invisible while items are being tested.
+
 
 ** Simple topics
 
+
 The simplest drill topic has no special structure. When such a topic is
 presented during a drill session, any subheadings are "collapsed" with their
 contents hidden. So, you could include the question as text beneath the main
 heading, and the answer within a subheading. For example:
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 * Item                                   :drill:
 What is the capital city of Estonia?
 
 ** The Answer
 Tallinn.
-#+END_EXAMPLE
+#+END_SRC
 
 When this item is presented for review, the text beneath the main heading will
 be visible, but the contents of the subheading ("The Answer") will be hidden.
 
 ** Cloze deletion
 
+
 Cloze deletion can be used in any drill topic regardless of whether it is
 otherwise 'simple', or is one of the specialised topic types discussed
 below. To use cloze deletion, one or more parts of the body of the topic is
 will be obscured. The text is then revealed after the user presses a key. For
 example:
 
-#+BEGIN_EXAMPLE
+
+#+BEGIN_SRC org
 * Item                                   :drill:
 The capital city of Estonia is [Tallinn].
-#+END_EXAMPLE
+#+END_SRC
 
 During review, the user will see:
 
 
 Example:
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 Type 1 hypersensitivity reactions are mediated by [immunoglobulin E|molecule]
 and [mast cells|cell type].
-#+END_EXAMPLE
+#+END_SRC
 
 #+BEGIN_QUOTE
 Type 1 hypersensitivity reactions are mediated by
 
 
 ** Two-sided cards
+# <<Two-sided cards>>
 
 The remaining topic types all use the topic property, =DRILL_CARD_TYPE=. This
 property tells =org-drill= which function to use to present the topic during
 the first two are considered as "notes" and will always be hidden during topic
 review.
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 * Noun                                               :drill:
     :PROPERTIES:
     :DRILL_CARD_TYPE: twosided
 ** Example sentence
 ¿Quién fue esa mujer?
 Who was that woman?
-#+END_EXAMPLE
+#+END_SRC
 
 In this example, the user will be shown the main text -- "Translate this word"
 -- and either 'la mujer', /or/ 'the woman', at random. The section 'Example
 
 
 ** Multi-sided cards
+# <<Multi-sided cards>>
+
 
 The =multisided= card type is similar to =twosided=, except that any
 subheading has a chance of being presented during the topic review. One
 subheading is always shown and all others are always hidden.
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 * Noun                                               :drill:
     :PROPERTIES:
     :DRILL_CARD_TYPE: multisided
 
 ** Picture
 [[file:table.jpg][PICTURE]]
-#+END_EXAMPLE
+#+END_SRC
 
 The user will be shown the main text and either 'la mujer', /or/ 'the woman',
 /or/ a picture of a table.
 
+
 ** Multi-cloze cards
+# <<Multi-cloze cards>>
+
 
 Often, you will wish to create cards out of sentences that express several
 facts, such as the following:
 
-#+BEGIN_QUOTE
+#+BEGIN_SRC org
 The capital city of New Zealand is Wellington, which is located in the
 South Island and has a population of about 400,000.
-#+END_QUOTE
+#+END_SRC
 
 There is more than one fact in this statement -- you could create a single
 'simple' card with all the facts marked as cloze text, like so:
 
-#+BEGIN_QUOTE
+#+BEGIN_SRC org
 The capital city of [New Zealand] is [Wellington], which is located in
-[the South Island] and has a population of about [400,000].
-#+END_QUOTE
+the [North|North/South] Island and has a population of about [400,000].
+#+END_SRC
 
 But this card will be difficult to remember. If you get just one of the 4
 hidden facts wrong, you will fail the card. A card like this is likely to
 several cards, with one fact per card. You might end up with something
 like this:
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 * Fact
 The capital city of [New Zealand] is Wellington, which has a population of
 about 400,000.
 
 * Fact
 The capital city of [New Zealand] is Wellington, which is located in the
-the South Island.
+the North Island.
 
 * Fact
 The capital city of New Zealand is [Wellington], which is located in
-the South Island.
+the North Island.
 
 * Fact
 The capital city of New Zealand is Wellington, which is located in
-[the South Island].
-#+END_EXAMPLE
+the [North|North/South] Island.
+#+END_SRC
 
 However, this is really cumbersome. The 'multicloze' card type exists for this
 situation. Multicloze cards behave like 'simple' cards, except that when there
 review, one of 'New Zealand', 'Wellington', 'the South Island' or '400,000'
 will be hidden.
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 * Fact
   :PROPERTIES:
   :DRILL_CARD_TYPE: multicloze
   :END:
 
 The capital city of [New Zealand] is [Wellington], which is located in
-[the South Island] and has a population of about [400,000].
-#+END_EXAMPLE
+the [North|North/South] Island and has a population of about [400,000].
+#+END_SRC
 
-** User-defined topic types
 
-Finally, you can write your own elisp functions to define new kinds of
+** User-defined card types
+# <<User-defined card types>>
+
+
+Finally, you can write your own emacs lisp functions to define new kinds of
 topics. Any new topic type will need to be added to
 =org-drill-card-type-alist=, and cards using that topic type will need to have
 it as the value of their =DRILL_CARD_TYPE= property. For an example, see the
 
 See the file [[file:spanish.org][spanish.org]] for a full set of example material.
 
-** Comments
-
-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, comments are always rendered invisible while items are
-being tested.
 
 
 * Running the drill session
 (your progress up to that point will be saved).
 
 
+* Cram mode
+
+
+There are some situations, such as before an exam, where you will want to
+revise all of your cards regardless of when they are next due for review.
+
+To do this, run a /cram session/ with the =org-drill-cram= command (=M-x
+org-drill-cram RET=). This works the same as a normal drill session, except
+that all items are considered due for review unless you reviewed them within
+the last 12 hours (you can change the number of hours by customising the
+variable =org-drill-cram-hours=).
+
+
 * Leeches
 # <<leeches>>
 
 See [[http://www.supermemo.com/help/leech.htm][the SuperMemo website]] for more on leeches.
 
 
-* Cram mode
+* Customisation
 
 
-There are some situations, such as before an exam, where you will want to
-revise all of your cards regardless of when they are next due for review.
+Org-Drill has several settings which you change using
+=M-x customize-group org-drill <RET>=. Alternatively you can change these
+settings by adding elisp code to your configuration file (=.emacs=).
 
-To do this, run a /cram session/ with the =org-drill-cram= command (=M-x
-org-drill-cram RET=). This works the same as a normal drill session, except
-that all items are considered due for review unless you reviewed them within
-the last 12 hours (you can change the number of hours by customising the
-variable =org-drill-cram-hours=).
+
+** Appearance of items during drill sessions
+
+
+If you want cloze-deleted text to show up in a special font within Org mode
+buffers, add this to your .emacs:
+
+#+BEGIN_SRC elisp
+(setq org-drill-use-visible-cloze-face-p t)
+#+END_SRC
+
+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_SRC elisp
+(setq org-drill-hide-item-headings-p t)
+#+END_SRC
+
+
+** Duration of drill sessions
+
+
+By default, a drill session will end when either 30 items have been
+successfully reviewed, or 20 minutes have passed. To change this behaviour, use
+the following settings.
+
+#+BEGIN_SRC elisp
+(setq org-drill-maximum-items-per-session 40)
+(setq org-drill-maximum-duration 30)   ; 30 minutes
+#+END_SRC
+
+If either of these variables is set to nil, then item count or elapsed time
+will not count as reasons to end the session. If both variables are nil, the
+session will not end until /all/ outstanding items have been reviewed.
+
+
+** Spaced repetition algorithm
+
+
+*** Choice of algorithm
+
+
+Org-Drill supports three different spaced repetition algorithms, all based on
+SuperMemo algorithms. These are:
+- [[http://www.supermemo.com/english/ol/sm2.htm][SM2]] :: an early algorithm, used in SuperMemo 2.0 (1988), which remains very
+  popular -- Anki and Mnemosyne, two of the most popular spaced repetition
+  programs, use SM2. This algorithm stores an 'ease factor' for each item,
+  which is modified each time you rate your recall of the item.
+- [[http://www.supermemo.com/english/ol/sm5.htm][SM5]] (default) :: used in SuperMemo 5.0 (1989). This algorithm uses 'ease
+     factors' but also uses a persistent, per-user 'matrix of optimal factors'
+     which is also modified after each item repetition.
+- Simple8 :: an experimental algorithm based on the [[http://www.supermemo.com/english/algsm8.htm][SM8]] algorithm. SM8 is used
+             in SuperMemo 8.0 (1998) and is almost identical to SM11 which is
+             used in SuperMemo 2002. Like SM5, it uses a matrix of optimal
+             factors. Simple8 differs from SM8 in that it does not adapt the
+             matrix to the individual user, though it does adapt each item's
+             'ease factor'.
+
+
+If you want Org-Drill to use the =SM2= algorithm, put the following in your
+=.emacs=:
+
+#+BEGIN_SRC elisp
+(setq org-drill-spaced-repetition-algorithm 'sm2)
+#+END_SRC
+
+
+*** Random variation of repetition intervals
+
+
+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_SRC elisp
+(setq org-drill-add-random-noise-to-intervals-p t)
+#+END_SRC
+
+
+*** Adjustment for early or late review of items
+
+
+Reviewing items earlier or later than their scheduled review date may affect
+how soon the next review date should be scheduled. Code to make this adjustment
+is also presented on the SuperMemo website. It can be enabled with:
+
+#+BEGIN_SRC elisp
+(setq org-drill-adjust-intervals-for-early-and-late-repetitions-p t)
+#+END_SRC
+
+This will affect both early and late repetitions if the Simple8 algorithm is
+used. For the SM5 algorithm it will affect early repetitions only. It has no
+effect on the SM2 algorithm.
+
+
+*** Adjusting item difficulty globally
+
+
+The =learn fraction= is a global value which affects how quickly the intervals
+(times between each retest of an item) increase with successive repetitions,
+for /all/ items. The default value is 0.5, and this is the value used in
+SuperMemo. For some collections of information, you may find that you are
+reviewing items too often (they are too easy and the workload is too high), or
+too seldom (you are failing them too often). In these situations, it is
+possible to alter the learn fraction from its default in order to increase or
+decrease the frequency of repetition of items over time. Increasing the value
+will make the time intervals grow faster, and lowering it will make them grow
+more slowly. The table below shows the growth in intervals (in days) with some
+different values of the learn fraction (F). The table assumes that the item is
+successfully recalled each time, with an average quality of just under 4.
+
+
+| Repetition | F=0.3 | F=0.4 | *F=0.5* | F=0.6 | F=0.7 |
+|------------+-------+-------+---------+-------+-------|
+| 1st        |     2 |     2 |       2 |     2 |     2 |
+| 2nd        |     7 |     7 |       7 |     7 |     7 |
+| 5th        |    26 |    34 |      46 |    63 |    85 |
+| 10th       |    85 |   152 |     316 |   743 |  1942 |
+| 15th       |   233 |   501 |    1426 |  5471 | 27868 |
+
+To alter the learn fraction, put the following in your .emacs:
+
+#+BEGIN_SRC elisp
+(setq org-drill-learn-fraction 0.45)   ; change the value as desired
+#+END_SRC
+
+
+** Per-file customisation settings
+
+
+Most of the above settings are safe as file-local variables. This means you can
+include a commented section like this at the end of your .org file to apply
+special settings when running a Drill session using that file:
+
+#+BEGIN_SRC org
+# Local Variables:
+# org-drill-maximum-items-per-session:    50
+# org-drill-spaced-repetition-algorithm:  simple8
+# End:
+#+END_SRC org
 
 
 * Incremental reading
 and most importantly, we need to define a couple of =org-capture= templates for
 captured facts.
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC elisp
 (setq org-capture-templates
        `(("u"
          "Task: Read this URL"
          :immediate-finish t)
         ;; ...other capture templates...
     ))
-#+END_EXAMPLE
+#+END_SRC
 
 Using these templates and =org-protocol=, you can set up buttons in your web
 browser to:
 has been turned into a drill item. Continuing the above example, you would see
 something like:
 
-#+BEGIN_EXAMPLE
+#+BEGIN_SRC org
 ** Fact: 'Tuberculosis - Wikipedia, the Free Encyclopedia'        :drill:
 
 Prevention relies on screening programs and vaccination, usually with Bacillus
 Calmette-Guérin vaccine.
-#+END_EXAMPLE
+#+END_SRC
 
 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
 or give it different tags or properties, for example.
 
 
-* Still to do
+* Still to do                                                         :noexport:
+
 
 - =org-drill-question-tag= should use a tag match string, rather than a
   single tag? Can use =org-make-tag-matcher=.

File org-drill.el

-;;; org-drill.el - Self-testing with org-learn
+;;; org-drill.el - Self-testing using spaced repetition
 ;;;
 ;;; Author: Paul Sexton <eeeickythump@gmail.com>
-;;; Version: 1.7
+;;; Version: 2.0
 ;;; Repository at http://bitbucket.org/eeeickythump/org-drill/
 ;;;
 ;;;
 ;;; Synopsis
 ;;; ========
 ;;;
-;;; Uses the spaced repetition algorithm in `org-learn' to conduct interactive
+;;; Uses the SuperMemo spaced repetition algorithms to conduct interactive
 ;;; "drill sessions", where the material to be remembered is presented to the
 ;;; student in random order. The student rates his or her recall of each item,
-;;; and this information is fed back to `org-learn' to schedule the item for
-;;; later revision.
+;;; and this information is used to schedule the item for later revision.
 ;;;
 ;;; Each drill session can be restricted to topics in the current buffer
 ;;; (default), one or several files, all agenda files, or a subtree. A single
   :type 'string)
 
 
-
 (defcustom org-drill-maximum-items-per-session
   30
   "Each drill session will present at most this many topics for review.
   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."
+interval for the card is reset to 0 days.  If the quality is higher
+than this number, it is regarded as successfully recalled, but the
+time interval to the next repetition will be lowered if the quality
+was near to a fail.
+
+By default this is 2, for SuperMemo-like behaviour. 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-forgetting-index
+  10
+  "What percentage of items do you consider it is 'acceptable' to
+forget each drill session? The default is 10%. A warning message
+is displayed at the end of the session if the percentage forgotten
+climbs above this number."
+  :group 'org-drill
+  :type 'integer)
+
+
 (defcustom org-drill-leech-failure-threshold
   15
   "If an item is forgotten more than this many times, it is tagged
   ;; ver 3!  "\\(\\[.*?\\]\\|\\[.*?[[:cntrl:]]+.*?\\]\\)"
   "\\(\\[[[:cntrl:][:graph:][:space:]]*?\\)\\(\\||.+?\\)\\(\\]\\)")
 
+
 (defvar org-drill-cloze-keywords
   `((,org-drill-cloze-regexp
      (1 'org-drill-visible-cloze-face nil)
 (defcustom org-drill-spaced-repetition-algorithm
   'sm5
   "Which SuperMemo spaced repetition algorithm to use for scheduling items.
-Available choices are SM2 and SM5."
+Available choices are:
+- SM2 :: the SM2 algorithm, used in SuperMemo 2.0
+- SM5 :: the SM5 algorithm, used in SuperMemo 5.0
+- Simple8 :: a modified version of the SM8 algorithm. SM8 is used in
+  SuperMemo 98. The version implemented here is simplified in that while it
+  'learns' the difficulty of each item using quality grades and number of
+  failures, it does not modify the matrix of values that
+  governs how fast the inter-repetition intervals increase. A method for
+  adjusting intervals when items are reviewed early or late has been taken
+  from SM11, a later version of the algorithm, and included in Simple8."
   :group 'org-drill
-  :type '(choice (const 'sm2) (const 'sm5)))
+  :type '(choice (const 'sm2) (const 'sm5) (const 'simple8)))
+
+
+
+(defcustom org-drill-optimal-factor-matrix
+  nil
+  "DO NOT CHANGE THE VALUE OF THIS VARIABLE.
+
+Persistent matrix of optimal factors, used by the SuperMemo SM5 algorithm.
+The matrix is saved (using the 'customize' facility) at the end of each
+drill session.
+
+Over time, values in the matrix will adapt to the individual user's
+pace of learning."
+  :group 'org-drill
+  :type 'sexp)
+
 
 (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."
+small, but scales up with the interval."
   :group 'org-drill
   :type 'boolean)
 
+
+(defcustom org-drill-adjust-intervals-for-early-and-late-repetitions-p
+  nil
+  "If true, when the student successfully reviews an item 1 or more days
+before or after the scheduled review date, this will affect that date of
+the item's next scheduled review, according to the algorithm presented at
+ [[http://www.supermemo.com/english/algsm11.htm#Advanced%20repetitions]].
+
+Items that were reviewed early will have their next review date brought
+forward. Those that were reviewed late will have their next review
+date postponed further.
+
+Note that this option currently has no effect if the SM2 algorithm
+is used."
+  :group 'org-drill
+  :type 'boolean)
+
+
 (defcustom org-drill-cram-hours
   12
   "When in cram mode, items are considered due for review if
 (defvar *org-drill-session-qualities* nil)
 (defvar *org-drill-start-time* 0)
 (defvar *org-drill-new-entries* nil)
+(defvar *org-drill-dormant-entry-count* 0)
 (defvar *org-drill-mature-entries* nil)
 (defvar *org-drill-failed-entries* nil)
 (defvar *org-drill-again-entries* nil)
 for review unless they were already reviewed in the recent past?")
 
 
+(defcustom org-drill-learn-fraction
+  0.5
+  "Fraction between 0 and 1 that governs how quickly the spaces
+between successive repetitions increase, for all items. The
+default value is 0.5. Higher values make spaces increase more
+quickly with each successful repetition. You should only change
+this in small increments (for example 0.05-0.1) as it has an
+exponential effect on inter-repetition spacing."
+  :group 'org-drill
+  :type 'float)
+
+
+;;; Make the above settings safe as file-local variables.
+
+
+(put 'org-drill-question-tag 'safe-local-variable 'stringp)
+(put 'org-drill-maximum-items-per-session 'safe-local-variable
+     '(lambda (val) (or (stringp val) (null val))))
+(put 'org-drill-maximum-duration 'safe-local-variable
+     '(lambda (val) (or (stringp val) (null val))))
+(put 'org-drill-failure-quality 'safe-local-variable 'integerp)
+(put 'org-drill-forgetting-index 'safe-local-variable 'integerp)
+(put 'org-drill-leech-failure-threshold 'safe-local-variable 'integerp)
+(put 'org-drill-leech-method 'safe-local-variable
+     '(lambda (val) (memq val '(nil skip warn))))
+(put 'org-drill-use-visible-cloze-face-p 'safe-local-variable 'booleanp)
+(put 'org-drill-hide-item-headings-p 'safe-local-variable 'booleanp)
+(put 'org-drill-spaced-repetition-algorithm 'safe-local-variable
+     '(lambda (val) (memq val '(simple8 sm5 sm2))))
+(put 'org-drill-add-random-noise-to-intervals-p 'safe-local-variable 'booleanp)
+(put 'org-drill-adjust-intervals-for-early-and-late-repetitions-p
+     'safe-local-variable 'booleanp)
+(put 'org-drill-cram-hours 'safe-local-variable 'integerp)
+(put 'org-drill-learn-fraction 'safe-local-variable 'floatp)
+
 
 ;;;; Utilities ================================================================
 
 
 (defun org-drill-entry-p ()
   "Is the current entry a 'drill item'?"
-  (or (org-entry-get (point) "LEARN_DATA")
-      ;;(assoc "LEARN_DATA" (org-entry-properties nil))
-      (member org-drill-question-tag (org-get-local-tags))))
+  ;;(or (org-entry-get (point) "LEARN_DATA")
+  ;;(assoc "LEARN_DATA" (org-entry-properties nil))
+  (member org-drill-question-tag (org-get-local-tags)))
 
 
 (defun org-part-of-drill-entry-p ()
       (and (org-drill-entry-p)
            (or (not (eql 'skip org-drill-leech-method))
                (not (org-drill-entry-leech-p)))
-           (or (null item-time)
+           (or (null item-time)         ; not scheduled
                (not (minusp             ; scheduled for today/in future
                      (- (time-to-days (current-time))
                         (time-to-days item-time))))))))))
          (null item-time))))
 
 
-
 (defun org-drill-entry-last-quality ()
   (let ((quality (org-entry-get (point) "DRILL_LAST_QUALITY")))
     (if quality
       nil)))
 
 
+(defun org-drill-entry-failure-count ()
+  (let ((quality (org-entry-get (point) "DRILL_FAILURE_COUNT")))
+    (if quality
+        (string-to-number quality)
+      0)))
+
+
+(defun org-drill-entry-average-quality (&optional default)
+  (let ((val (org-entry-get (point) "DRILL_AVERAGE_QUALITY")))
+    (if val
+        (string-to-number val)
+      (or default nil))))
+
+(defun org-drill-entry-last-interval (&optional default)
+  (let ((val (org-entry-get (point) "DRILL_LAST_INTERVAL")))
+    (if val
+        (string-to-number val)
+      (or default 0))))
+
+(defun org-drill-entry-repeats-since-fail (&optional default)
+  (let ((val (org-entry-get (point) "DRILL_REPEATS_SINCE_FAIL")))
+    (if val
+        (string-to-number val)
+      (or default 0))))
+
+(defun org-drill-entry-total-repeats (&optional default)
+  (let ((val (org-entry-get (point) "DRILL_TOTAL_REPEATS")))
+    (if val
+        (string-to-number val)
+      (or default 0))))
+
+(defun org-drill-entry-ease (&optional default)
+  (let ((val (org-entry-get (point) "DRILL_EASE")))
+    (if val
+        (string-to-number val)
+      default)))
+
+
+;;; 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 org-drill-early-interval-factor (optimal-factor
+                                                optimal-interval
+                                                days-ahead)
+  "Arguments:
+- OPTIMAL-FACTOR: interval-factor if the item had been tested
+exactly when it was supposed to be.
+- OPTIMAL-INTERVAL: interval for next repetition (days) if the item had been
+tested exactly when it was supposed to be.
+- DAYS-AHEAD: how many days ahead of time the item was reviewed.
+
+Returns an adjusted optimal factor which should be used to
+calculate the next interval, instead of the optimal factor found
+in the matrix."
+  (let ((delta-ofmax (* (1- optimal-factor)
+                    (/ (+ optimal-interval
+                          (* 0.6 optimal-interval) -1) (1- optimal-interval)))))
+    (- optimal-factor
+       (* delta-ofmax (/ days-ahead (+ days-ahead (* 0.6 optimal-interval)))))))
+
+
+(defun org-drill-get-item-data ()
+  "Returns a list of 6 items, containing all the stored recall
+  data for the item at point:
+- LAST-INTERVAL is the interval in days that was used to schedule the item's
+  current review date.
+- REPEATS is the number of items the item has been successfully recalled without
+  without any failures. It is reset to 0 upon failure to recall the item.
+- FAILURES is the total number of times the user has failed to recall the item.
+- TOTAL-REPEATS includes both successful and unsuccessful repetitions.
+- AVERAGE-QUALITY is the mean quality of recall of the item over
+  all its repetitions, successful and unsuccessful.
+- EASE is a number reflecting how easy the item is to learn. Higher is easier.
+"
+  (let ((learn-str (org-entry-get (point) "LEARN_DATA"))
+        (repeats (org-drill-entry-total-repeats :missing)))
+    (cond
+     (learn-str
+      (let ((learn-data (or (and learn-str
+                                 (read learn-str))
+                            (copy-list initial-repetition-state))))
+        (list (nth 0 learn-data)        ; last interval
+              (nth 1 learn-data)        ; repetitions
+              (org-drill-entry-failure-count)
+              (nth 1 learn-data)
+              (org-drill-entry-last-quality)
+              (nth 2 learn-data)        ; EF
+              )))
+     ((not (eql :missing repeats))
+      (list (org-drill-entry-last-interval)
+            (org-drill-entry-repeats-since-fail)
+            (org-drill-entry-failure-count)
+            (org-drill-entry-total-repeats)
+            (org-drill-entry-average-quality)
+            (org-drill-entry-ease)))
+     (t  ; virgin item
+      (list 0 0 0 0 nil nil)))))
+
+
+(defun org-drill-store-item-data (last-interval repeats failures
+                                                total-repeats meanq
+                                                ease)
+  "Stores the given data in the item at point."
+  (org-entry-delete (point) "LEARN_DATA")
+  (org-set-property "DRILL_LAST_INTERVAL"
+                    (number-to-string (round-float last-interval 4)))
+  (org-set-property "DRILL_REPEATS_SINCE_FAIL" (number-to-string repeats))
+  (org-set-property "DRILL_TOTAL_REPEATS" (number-to-string total-repeats))
+  (org-set-property "DRILL_FAILURE_COUNT" (number-to-string failures))
+  (org-set-property "DRILL_AVERAGE_QUALITY"
+                    (number-to-string (round-float meanq 3)))
+  (org-set-property "DRILL_EASE"
+                    (number-to-string (round-float ease 3))))
+
+
+
 ;;; SM2 Algorithm =============================================================
 
 
-(defun determine-next-interval-sm2 (last-interval n ef quality of-matrix)
+(defun determine-next-interval-sm2 (last-interval n ef quality
+                                                  failures meanq total-repeats)
   "Arguments:
 - LAST-INTERVAL -- the number of days since the item was last reviewed.
-- N -- the number of times the item has been successfully reviewed
+- REPEATS -- 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:
+Returns a list: (INTERVAL REPEATS EF FAILURES MEAN TOTAL-REPEATS OFMATRIX), where:
 - INTERVAL is the number of days until the item should next be reviewed
-- N is incremented by 1.
+- REPEATS is incremented by 1.
 - EF is modified based on the recall quality for the item.
 - OF-MATRIX is not modified."
   (assert (> n 0))
   (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)
+      (list -1 1 ef (1+ failures) meanq (1+ total-repeats)
+            org-drill-optimal-factor-matrix)
     ;; else:
     (let* ((next-ef (modify-e-factor ef quality))
            (interval
                   (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))))
+             (t (* last-interval next-ef)))))
+      (list (if org-drill-add-random-noise-to-intervals-p
+                (+ last-interval (* (- interval last-interval)
+                                    (org-drill-random-dispersal-factor)))
+              interval)
+            (1+ n)
+            next-ef
+            failures meanq (1+ total-repeats)
+            org-drill-optimal-factor-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)))
+  (let ((of (get-optimal-factor n ef (or of-matrix
+                                         org-drill-optimal-factor-matrix))))
     (if (= 1 n)
 	of
       (* of last-interval))))
 
 
-(defun determine-next-interval-sm5 (last-interval n ef quality of-matrix)
+(defun determine-next-interval-sm5 (last-interval n ef quality
+                                                  failures meanq total-repeats
+                                                  of-matrix &optional delta-days)
+  (if (zerop n) (setq n 1))
+  (if (null ef) (setq ef 2.5))
   (assert (> n 0))
   (assert (and (>= quality 0) (<= quality 5)))
+  (unless of-matrix
+    (setq of-matrix org-drill-optimal-factor-matrix))
+  (setq of-matrix (cl-copy-tree of-matrix))
+
+  (setq meanq (if meanq
+                  (/ (+ quality (* meanq total-repeats 1.0))
+                     (1+ total-repeats))
+                quality))
+
   (let ((next-ef (modify-e-factor ef quality))
         (old-ef ef)
+        (new-of (modify-of (get-optimal-factor n ef of-matrix)
+                           quality org-drill-learn-fraction))
         (interval nil))
+    (when (and org-drill-adjust-intervals-for-early-and-late-repetitions-p
+               delta-days (minusp delta-days))
+      (setq new-of (org-drill-early-interval-factor
+                    (get-optimal-factor n ef of-matrix)
+                    (inter-repetition-interval-sm5
+                     last-interval n ef of-matrix)
+                    delta-days)))
+
     (setq of-matrix
           (set-optimal-factor n next-ef of-matrix
-                              (round-float
-                               (modify-of (get-optimal-factor n ef of-matrix)
-                                          quality org-learn-fraction)
-                               3)))     ; round OF to 3 d.p.
+                              (round-float new-of 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 old-ef of-matrix))     ; Not clear if OF matrix is supposed to
-                                        ; be preserved
+      (list -1 1 old-ef (1+ failures) meanq (1+ total-repeats)
+            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
+     ;; ((and (>= quality 4)
+     ;;       (not org-learn-always-reschedule))
+     ;;  (list 0 (1+ n) ef failures meanq
+     ;;        (1+ total-repeats) of-matrix))     ; 0 interval = unschedule
      (t
       (setq interval (inter-repetition-interval-sm5
                       last-interval n ef of-matrix))
           (setq interval (+ last-interval
                             (* (- interval last-interval)
                                (org-drill-random-dispersal-factor)))))
-      (list (round interval) (1+ n) ef of-matrix)))))
+      (list interval
+            (1+ n)
+            ef
+            failures
+            meanq
+            (1+ total-repeats)
+            of-matrix)))))
+
+
+;;; Simple8 Algorithm =========================================================
+
+
+(defun org-drill-simple8-first-interval (failures)
+  "Arguments:
+- FAILURES: integer >= 0. The total number of times the item has
+  been forgotten, ever.
+
+Returns the optimal FIRST interval for an item which has previously been
+forgotten on FAILURES occasions."
+  (* 2.4849 (exp (* -0.057 failures))))
+
+
+(defun org-drill-simple8-interval-factor (ease repetition)
+  "Arguments:
+- EASE: floating point number >= 1.2. Corresponds to `AF' in SM8 algorithm.
+- REPETITION: the number of times the item has been tested.
+1 is the first repetition (ie the second trial).
+Returns:
+The factor by which the last interval should be
+multiplied to give the next interval. Corresponds to `RF' or `OF'."
+  (+ 1.2 (* (- ease 1.2) (expt org-drill-learn-fraction (log repetition 2)))))
+
+
+(defun org-drill-simple8-quality->ease (quality)
+  "Returns the ease (`AF' in the SM8 algorithm) which corresponds
+to a mean item quality of QUALITY."
+  (+ (* 0.0542 (expt quality 4))
+     (* -0.4848 (expt quality 3))
+     (* 1.4916 (expt quality 2))
+     (* -1.2403 quality)
+     1.4515))
+
+
+(defun determine-next-interval-simple8 (last-interval repeats quality
+                                                      failures meanq totaln
+                                                      &optional delta-days)
+  "Arguments:
+- LAST-INTERVAL -- the number of days since the item was last reviewed.
+- REPEATS -- the number of times the item has been successfully reviewed
+- EASE -- the 'easiness factor'
+- QUALITY -- 0 to 5
+- DELTA-DAYS -- how many days overdue was the item when it was reviewed.
+  0 = reviewed on the scheduled day. +N = N days overdue.
+  -N = reviewed N days early.
+
+Returns the new item data, as a list of 6 values:
+- NEXT-INTERVAL
+- REPEATS
+- EASE
+- FAILURES
+- AVERAGE-QUALITY
+- TOTAL-REPEATS.
+See the documentation for `org-drill-get-item-data' for a description of these."
+  (assert (>= repeats 0))
+  (assert (and (>= quality 0) (<= quality 5)))
+  (assert (or (null meanq) (and (>= meanq 0) (<= meanq 5))))
+  (let ((next-interval nil))
+    (setf meanq (if meanq
+                    (/ (+ quality (* meanq totaln 1.0)) (1+ totaln))
+                  quality))
+    (cond
+     ((or (zerop repeats)
+          (zerop last-interval))
+      (setf next-interval (org-drill-simple8-first-interval failures))
+      (incf repeats)
+      (incf totaln))
+     (t
+      (cond
+       ((<= quality org-drill-failure-quality)
+        (incf failures)
+        (setf repeats 0
+              next-interval -1))
+       (t
+        (let* ((use-n
+                (if (and
+                     org-drill-adjust-intervals-for-early-and-late-repetitions-p
+                     (numberp delta-days) (plusp delta-days)
+                     (plusp last-interval))
+                    (+ repeats (min 1 (/ delta-days last-interval 1.0)))
+                  repeats))
+               (factor (org-drill-simple8-interval-factor
+                        (org-drill-simple8-quality->ease meanq) use-n))
+               (next-int (* last-interval factor)))
+          (when (and org-drill-adjust-intervals-for-early-and-late-repetitions-p
+                     (numberp delta-days) (minusp delta-days))
+            ;; The item was reviewed earlier than scheduled.
+            (setf factor (org-drill-early-interval-factor
+                          factor next-int (abs delta-days))
+                  next-int (* last-interval factor)))
+          (setf next-interval next-int)
+          (incf repeats)
+          (incf totaln))))))
+    (list
+     (if (and org-drill-add-random-noise-to-intervals-p
+              (plusp next-interval))
+         (+ last-interval (* (- next-interval last-interval)
+                             (org-drill-random-dispersal-factor)))
+       next-interval)
+     repeats
+     (org-drill-simple8-quality->ease meanq)
+     failures
+     meanq
+     totaln
+     )))
+
+
 
 
 ;;; Essentially copied from `org-learn.el', but modified to
 (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))
-			 (copy-list initial-repetition-state)))
-	 closed-dates)
-    (setq learn-data
+  (let ((delta-days (- (time-to-days (current-time))
+                   (time-to-days (or (org-get-scheduled-time (point))
+                                     (current-time)))))
+        (ofmatrix org-drill-optimal-factor-matrix))
+    (destructuring-bind (last-interval repetitions failures
+                                       total-repeats meanq ease)
+        (org-drill-get-item-data)
+      (destructuring-bind (next-interval repetitions ease
+                                         failures meanq total-repeats
+                                         &optional new-ofmatrix)
           (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)))))
-    (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))
-      (org-schedule t))
-     ((minusp (first learn-data))
-      (org-schedule nil (current-time)))
-     (t
-      (org-schedule nil (time-add (current-time)
-				  (days-to-time (nth 0 learn-data))))))))
+            (sm5 (determine-next-interval-sm5 last-interval repetitions
+                                              ease quality failures
+                                              meanq total-repeats ofmatrix))
+            (sm2 (determine-next-interval-sm2 last-interval repetitions
+                                              ease quality failures
+                                              meanq total-repeats))
+            (simple8 (determine-next-interval-simple8 last-interval repetitions
+                                                      quality failures meanq
+                                                      total-repeats
+                                                      delta-days)))
+        (if (integerp days-ahead)
+            (setf next-interval days-ahead))
+        (org-drill-store-item-data next-interval repetitions failures
+                                   total-repeats meanq ease)
+        (if (eql 'sm5 org-drill-spaced-repetition-algorithm)
+            (setq org-drill-optimal-factor-matrix new-ofmatrix))
+
+        (cond
+         ((= 0 days-ahead)
+          (org-schedule t))
+         ((minusp days-ahead)
+          (org-schedule nil (current-time)))
+         (t
+          (org-schedule nil (time-add (current-time)
+                                      (days-to-time
+                                       (round next-interval))))))))))