#include <sys/types.h>
#include <sys/time.h>
+#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
CATEGORY_ORDER_SEQUENTIAL
} category_order_t;
+typedef enum {
+ CHALLENGE_TYPE_TEXT,
+ CHALLENGE_TYPE_IMAGE
+} challenge_type_t;
+
typedef struct _category {
char *name;
int items_size;
/* Support categories where responses are timed (0.0 == disable). */
double time_limit;
int bin_zero_head;
+ /* Support challenges of non-text types (image, audio, etc.) */
+ challenge_type_t challenge_type;
} category_t;
typedef struct _mnemon {
category->order = CATEGORY_ORDER_RANDOM;
category->time_limit = 0.0;
category->bin_zero_head = 0;
+ category->challenge_type = CHALLENGE_TYPE_TEXT;
}
static void
fprintf (file, "time = %f\n\n",
category->time_limit);
+ fprintf (file, "challenge = ");
+ switch (category->challenge_type) {
+ case CHALLENGE_TYPE_TEXT:
+ fprintf (file, "text");
+ break;
+ case CHALLENGE_TYPE_IMAGE:
+ fprintf (file, "image");
+ break;
+ }
+ fprintf (file, "\n\n");
+
for (i = 0; i < category->num_items; i++) {
item = &category->items[i];
if (i != 0)
value, path, line_count);
exit (1);
}
+ } else if (strcmp (name, "challenge") == 0) {
+ if (strcmp (value, "text") == 0) {
+ category->challenge_type = CHALLENGE_TYPE_TEXT;
+ } else if (strcmp (value, "image") == 0) {
+ category->challenge_type = CHALLENGE_TYPE_IMAGE;
+ } else {
+ fprintf (stderr, "Unknown value for \"challenge\" option \"%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);
category_print (category, file);
+ fsync (fileno (file));
fclose (file);
err = rename (lock_filename, filename);
bin_add_item (bin, item);
}
+static void
+mnemon_show_image (mnemon_t *mnemon, const char *filename)
+{
+ char *command;
+
+ /* XXX: Yes, shelling out to system is total cheese. The planned
+ * fix here is to bring graphical display in process, (or at least
+ * have a custom external program that accepts image filenames on
+ * stdin.
+ */
+ xasprintf (&command, "xli -gamma 2.2 %s >/dev/null 2>&1 &",
+ filename);
+ system (command);
+ free (command);
+}
+
+static void
+mnemon_hide_image (mnemon_t *mnemon)
+{
+ char * command;
+
+ /* XXX: And this is just embarrassing (obviously wrong in several
+ * ways). Hopefully I'll amend away any commit that includes this.
+ */
+ xasprintf (&command, "killall xli");
+ system (command);
+ free (command);
+}
+
static void
mnemon_do_challenges (mnemon_t *mnemon)
{
while (1) {
if (category->time_limit > 0.0) {
- readline ("The next one is timed. Press enter when ready:");
+ response = readline ("The next one is timed. Press enter when ready:");
+ free (response);
+ }
+
+ switch (category->challenge_type) {
+ case CHALLENGE_TYPE_TEXT:
+ printf ("%s\n", item->challenge);
+ break;
+ case CHALLENGE_TYPE_IMAGE:
+ {
+ char *absolute_filename;
+
+ xasprintf (&absolute_filename, "%s/%s",
+ mnemon->dir_name, item->challenge);
+ mnemon_show_image (mnemon, absolute_filename);
+ free (absolute_filename);
+ }
+ break;
}
-
- printf ("%s\n", item->challenge);
gettimeofday (&start, NULL);
response = readline ("> ");
gettimeofday (&end, NULL);
+ if (category->challenge_type == CHALLENGE_TYPE_IMAGE)
+ mnemon_hide_image (mnemon);
+
/* Terminate on EOF */
if (response == NULL) {
printf ("\n");
return;
}
- if (response[0] == '/')
+ if (response[0] == '/') {
mnemon_handle_command (mnemon, response + 1);
- else
+ free (response);
+ } else {
break;
+ }
}
mnemon_handle_response (mnemon, bin, item_index,
(end.tv_sec + end.tv_usec / 1e6) -
(start.tv_sec + start.tv_usec / 1e6),
category->time_limit);
+ free (response);
} while (mnemon->to_introduce ||
mnemon->unlearned ||
mnemon->to_master > 0);
-
- printf ("Great job.\n");
}
int
main (int argc, char *argv[])
{
mnemon_t mnemon;
+ char *response;
srand (time (NULL));
mnemon_fini (&mnemon);
+ mnemon_init (&mnemon);
+ mnemon_load (&mnemon);
+
+ printf ("Great job.\nHere are your current results:\n");
+ mnemon_print_histogram (&mnemon, NULL, 0);
+ response = readline ("Press enter to quit.\n");
+ free (response);
+
+ mnemon_fini (&mnemon);
+
return 0;
}