The syntax is, for example 'time = 2.0' in the data file, meaning
that each answer in that category needs to be answered in less than
2.0 seconds or it will be handled as an incorrect answer even if
correct. (Good for practicing multiplication facts, for example.)
#include <math.h>
#include <sys/types.h>
#include <math.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
/* Support sequential introduction of items from bin 0 */
category_order_t order;
/* Support sequential introduction of items from bin 0 */
category_order_t order;
+ /* Support categories where responses are timed (0.0 == disable). */
+ double time_limit;
int bin_zero_head;
} category_t;
int bin_zero_head;
} category_t;
category->num_items = 0;
category->items = NULL;
category->order = CATEGORY_ORDER_RANDOM;
category->num_items = 0;
category->items = NULL;
category->order = CATEGORY_ORDER_RANDOM;
+ category->time_limit = 0.0;
category->bin_zero_head = 0;
}
category->bin_zero_head = 0;
}
fprintf (file, "order = %s\n\n",
category->order == CATEGORY_ORDER_RANDOM ? "random" : "sequential");
fprintf (file, "order = %s\n\n",
category->order == CATEGORY_ORDER_RANDOM ? "random" : "sequential");
+ fprintf (file, "time = %f\n\n",
+ category->time_limit);
for (i = 0; i < category->num_items; i++) {
item = &category->items[i];
for (i = 0; i < category->num_items; i++) {
item = &category->items[i];
value, path, line_count);
exit (1);
}
value, path, line_count);
exit (1);
}
+ } else if (strcmp (name, "time") == 0) {
+ double limit;
+ char *end;
+ limit = strtod (value, &end);
+ while (isspace (*end))
+ end++;
+ if (*end == '\0') {
+ category->time_limit = limit;
+ } else {
+ fprintf (stderr, "Failed to parse time value: %s at %s:%d\n",
+ value, path, line_count);
+ exit (1);
+ }
} else {
fprintf (stderr, "Unknown option %s at %s:%d\n",
name, path, line_count);
} else {
fprintf (stderr, "Unknown option %s at %s:%d\n",
name, path, line_count);
static void
mnemon_select_item (mnemon_t *mnemon,
bin_t **bin_ret,
static void
mnemon_select_item (mnemon_t *mnemon,
bin_t **bin_ret,
+ int *item_index_ret,
+ category_t **category_ret)
{
int bin_index, item_index;
bin_t *bin;
{
int bin_index, item_index;
bin_t *bin;
+ item_t *item;
+ category_t *category;
bin_index = rand_within_exponential (mnemon->num_bins);
bin_index = rand_within_exponential (mnemon->num_bins);
item_index = rand_within (bin->num_items);
item_index = rand_within (bin->num_items);
- if (bin->score == 0) {
- category_t *category;
- item_t *item;
-
- item = bin->items[item_index];
-
- category = mnemon_item_category (mnemon, item);
+ item = bin->items[item_index];
+ category = mnemon_item_category (mnemon, item);
if (category->order == CATEGORY_ORDER_SEQUENTIAL) {
item = category_next_bin_zero_item (category);
if (item)
if (category->order == CATEGORY_ORDER_SEQUENTIAL) {
item = category_next_bin_zero_item (category);
if (item)
*bin_ret = bin;
*item_index_ret = item_index;
*bin_ret = bin;
*item_index_ret = item_index;
+ *category_ret = category;
bin_t *bin,
int item_index,
item_t *item,
bin_t *bin,
int item_index,
item_t *item,
+ const char *response,
+ double response_time,
+ double time_limit)
mnemon_remove_bin (mnemon, bin);
}
mnemon_remove_bin (mnemon, bin);
}
+ if (correct &&
+ (time_limit == 0.0 || response_time < time_limit))
+ {
item->score++;
mnemon->to_master--;
/* We reserve an item score of 0 for an item that has
item->score++;
mnemon->to_master--;
/* We reserve an item score of 0 for an item that has
printf ("Masterful (%dx).", item->score);
}
} else {
printf ("Masterful (%dx).", item->score);
}
} else {
- printf (" %s is the correct answer.",
- item->response);
+ if (! correct)
+ printf (" %s is the correct answer.",
+ item->response);
+ else
+ printf ("Correct, but not quite quick enough (%0.2f seconds---needed %0.2f seconds)\n",
+ response_time, time_limit);
/* Penalize an incorrect response by forcing the score
* negative. */
if (item->score >= 0) {
/* Penalize an incorrect response by forcing the score
* negative. */
if (item->score >= 0) {
bin_t *bin;
int item_index;
item_t *item;
bin_t *bin;
int item_index;
item_t *item;
- mnemon_select_item (mnemon, &bin, &item_index);
+ struct timeval start, end;
+
+ mnemon_select_item (mnemon, &bin, &item_index, &category);
item = bin->items[item_index];
if (bin->score == 0)
mnemon->to_introduce--;
while (1) {
item = bin->items[item_index];
if (bin->score == 0)
mnemon->to_introduce--;
while (1) {
+ if (category->time_limit > 0.0) {
+ readline ("The next one is timed. Press enter when ready:");
+ }
+
printf ("%s\n", item->challenge);
printf ("%s\n", item->challenge);
+ gettimeofday (&start, NULL);
response = readline ("> ");
response = readline ("> ");
+ gettimeofday (&end, NULL);
+
/* Terminate on EOF */
if (response == NULL) {
printf ("\n");
/* Terminate on EOF */
if (response == NULL) {
printf ("\n");
}
mnemon_handle_response (mnemon, bin, item_index,
}
mnemon_handle_response (mnemon, bin, item_index,
+ item, response,
+ (end.tv_sec + end.tv_usec / 1e6) -
+ (start.tv_sec + start.tv_usec / 1e6),
+ category->time_limit);
} while (mnemon->to_introduce ||
mnemon->unlearned ||
mnemon->to_master > 0);
} while (mnemon->to_introduce ||
mnemon->unlearned ||
mnemon->to_master > 0);