Remove the enumeration of challenge types.
[mnemon] / mnemon.h
1 /* mnemon - A memory training library
2  *
3  * Copyright © 2006,2011 Carl Worth
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA."
18  */
19
20 #ifndef MNEMON_H_INCLUDED
21 #define MNEMON_H_INCLUDED
22
23 #define unused(foo) foo __attribute__((unused))
24
25 typedef int bool_t;
26
27 typedef struct _item {
28     int score;
29     char *challenge;
30     char *response;
31 } item_t;
32
33 typedef struct _bin {
34     int score;
35     int items_size;
36     int num_items;
37     item_t **items;
38 } bin_t;
39
40 typedef enum {
41     CATEGORY_ORDER_RANDOM,
42     CATEGORY_ORDER_SEQUENTIAL
43 } category_order_t;
44
45 typedef struct _category {
46     char *name;
47     int items_size;
48     int num_items;
49     item_t *items;
50
51     /* Support sequential introduction of items from bin 0 */
52     category_order_t order;
53     /* Support categories where responses are timed (0.0 == disable). */
54     double time_limit;
55     int bin_zero_head;
56     /* Support challenges of non-text types (image, audio, etc.) */
57     char *challenge_type;
58     /* Whether to repeat afterwards (for a little extra reinforcement) */
59     bool_t repeat;
60 } category_t;
61
62 typedef struct _mnemon {
63     char *dir_name;
64
65     int categories_size;
66     int num_categories;
67     category_t *categories;
68
69     int bins_size;
70     int num_bins;
71     bin_t *bins;
72 } mnemon_t;
73
74 /* Initialize a new mnemon object. This function must be called before
75  * any other mnemon functions are used. */
76 void
77 mnemon_init (mnemon_t *mnemon);
78
79 /* Inidicate the caller is finished with a mnemon object. Free all
80  * resources associated with this object. After this call, the given
81  * mnemon object should not be passed to any other menmon function,
82  * (except mnemon_init to start over). */
83 void
84 mnemon_fini (mnemon_t *mnemon);
85
86 /* Load a specific category of mnemon challenges. The name should
87  * indicate the name of a file within the user's .mnemon directory. */
88 void
89 mnemon_load_category (mnemon_t          *mnemon,
90                       const char        *name);
91
92 /* Load all categories of mnemon challenges.
93  *
94  * This is equivalent to calling mnemon_load_category for all files
95  * found within the user's .mnemon directory. */
96 void
97 mnemon_load (mnemon_t *mnemon);
98
99 /* Select the next (weighted) random item to challenge the user.
100  *
101  * This function provides four return values (and yes, that's
102  * exceedingly awkward and a simpler interface should be designed to
103  * replace this):
104  *
105  *      bin:            The bin from which the item was selected
106  *
107  *      item_index:     The index within the bin of the slected item
108  *
109  *      category:       The name of the category for this item
110  *
111  *      introduced:     A flag indicating whether this is a newly
112  *                      introduced item. Items from bin 0 always count
113  *                      as newly introduced. If there is no bin 0,
114  *                      then items from the lowest non-negative bin
115  *                      will be flagged as introduced.
116  *
117  * The selection system is designed to rapidly reinforce items needing
118  * to be learned and provide exponentially less reinforcement for
119  * items as mastery is displayed. This is achieved by storing the
120  * items in a series of numbered bins.
121  *
122  * Items start in bin 0 indicating that they have never been presented
123  * to a user. When an item is presented to the user and answered
124  * correctly, it is moved into the bin of the next higher number.
125  *
126  * However, when an item is answered incorrectly, it is moved directly
127  * to bin -2 (if coming from a bin of a positive number), or the bin
128  * of the next lower integer (more negative) if coming from a bin of a
129  * negative number.
130  *
131  * When selecting a new item to challenge, first a bin is chosen
132  * (considering only the non-empty bins). The bin with the lowest
133  * number is the most likely to be chosen, while each succesively-
134  * higher-numbered bin has a probability one-half of that of the
135  * previous bin.
136  */
137 void
138 mnemon_select_item (mnemon_t     *mnemon,
139                     bin_t       **bin_ret,
140                     int          *item_index_ret,
141                     category_t  **category_ret,
142                     int          *introduced_ret);
143
144 /* Update an item based on a user's answer (correct or incorrect).
145  *
146  * The bin and item_index should be exactly as returned by
147  * mnemon_select_item.  The correct flag should indicate whether the
148  * user answered the challenge correctly or not, (and should only
149  * count as correct if the answer was within the time limit, if any).
150  *
151  * The item will be moved from its current bin to a new bin based on
152  * whether the challenge was answered correctly. The bin updates are
153  * as follows:
154  *
155  * If the answer was correct:
156  *      Increase the bin number by 1
157  *      If the new bin number is 0, set it to 1 (0 bin is for new items)
158  *
159  * If the answer was incorrect:
160  *      If the old bin was positive, move to bin -2 (for extra training)
161  *      Otherwise decrease the bin number by 1
162  *
163  * Note: All item and bin movement is kept only in memory. In order to
164  * save this progress to disk, the caller must call mnemon_save.
165  */
166 void
167 mnemon_score_item (mnemon_t *mnemon,
168                    bin_t *bin,
169                    unsigned int item_index,
170                    bool_t correct);
171
172 /* Save the user's progress by updating the category files in the
173  * users .mnemon directory. */
174 void
175 mnemon_save (mnemon_t *mnemon);
176
177 /* Remove a bin of a particular number.
178  *
179  * This can be useful in situations such as wanting to practice
180  * mastery of learned items without mixing in new items that the user
181  * has never seen before. This could be achieved by removing bin 0,
182  * for example.
183  */
184 void
185 mnemon_remove_bin (mnemon_t *mnemon, int bin_number);
186
187 /* Find the category to which an item belongs. */
188 category_t *
189 mnemon_item_category (mnemon_t  *mnemon,
190                       item_t    *item);
191
192 /* Get a category by name if it exists */
193 category_t *
194 mnemon_get_category_if_exists (mnemon_t     *mnemon,
195                                const char   *name);
196
197
198 #endif