From f9d10dd0b3a4f0abf144fb0c1fbe758ad73faa90 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 27 Mar 2009 15:05:08 -0700 Subject: [PATCH] Add support for image-based challenges The support right now is extremely cheesy. It depends on two external programs (xli and killall), and also uses system() to execute them with the shell (ick). Oh, and it will also indiscriminately kill any innocent xli processes that happen to get in the way. Clearly it's a pretty ugly hack. --- mnemon.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/mnemon.c b/mnemon.c index 5ce7364..d0a9609 100644 --- a/mnemon.c +++ b/mnemon.c @@ -55,6 +55,11 @@ typedef enum { 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; @@ -66,6 +71,8 @@ typedef struct _category { /* 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 { @@ -193,6 +200,7 @@ category_init (category_t *category, category->order = CATEGORY_ORDER_RANDOM; category->time_limit = 0.0; category->bin_zero_head = 0; + category->challenge_type = CHALLENGE_TYPE_TEXT; } static void @@ -262,6 +270,17 @@ category_print (category_t *category, 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) @@ -618,6 +637,16 @@ mnemon_load_category (mnemon_t *mnemon, 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); @@ -1102,6 +1131,35 @@ mnemon_handle_response (mnemon_t *mnemon, 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) { @@ -1156,13 +1214,30 @@ mnemon_do_challenges (mnemon_t *mnemon) response = readline ("The next one is timed. Press enter when ready:"); free (response); } - - printf ("%s\n", item->challenge); + + 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; + } 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"); -- 2.43.0