]> git.cworth.org Git - mnemon/blobdiff - mnemon.c
Add a simple text-to-speech challenge type.
[mnemon] / mnemon.c
index 87e1fd08b6530089cca9d12270405d0b1569d1c7..3dee0347e153c5e2a5c00f93d717f57605fd787d 100644 (file)
--- a/mnemon.c
+++ b/mnemon.c
@@ -64,7 +64,9 @@ typedef enum {
 typedef enum {
     CHALLENGE_TYPE_TEXT,
     CHALLENGE_TYPE_IMAGE,
-    CHALLENGE_TYPE_AUDIO
+    CHALLENGE_TYPE_AUDIO,
+    CHALLENGE_TYPE_MIDI,
+    CHALLENGE_TYPE_TEXT_TO_SPEECH
 } challenge_type_t;
 
 typedef struct _category {
@@ -80,6 +82,8 @@ typedef struct _category {
     int bin_zero_head;
     /* Support challenges of non-text types (image, audio, etc.) */
     challenge_type_t challenge_type;
+    /* Whether to repeat afterwards (for a little extra reinforcement) */
+    bool_t repeat;
 } category_t;
 
 typedef struct _mnemon {
@@ -208,6 +212,7 @@ category_init (category_t *category,
     category->time_limit = 0.0;
     category->bin_zero_head = 0;
     category->challenge_type = CHALLENGE_TYPE_TEXT;
+    category->repeat = 0;
 }
 
 static void
@@ -288,9 +293,17 @@ category_print (category_t *category,
     case CHALLENGE_TYPE_AUDIO:
        fprintf (file, "audio");
        break;
+    case CHALLENGE_TYPE_MIDI:
+       fprintf (file, "midi");
+       break;
+    case CHALLENGE_TYPE_TEXT_TO_SPEECH:
+       fprintf (file, "text-to-speech");
+       break;
     }
     fprintf (file, "\n\n");
 
+    fprintf (file, "repeat = %d\n\n", category->repeat);
+
     for (i = 0; i < category->num_items; i++) {
        item = &category->items[i];
        if (i != 0)
@@ -654,11 +667,20 @@ mnemon_load_category (mnemon_t            *mnemon,
                category->challenge_type = CHALLENGE_TYPE_IMAGE;
            } else if (strcmp (value, "audio") == 0) {
                category->challenge_type = CHALLENGE_TYPE_AUDIO;
+           } else if (strcmp (value, "midi") == 0) {
+               category->challenge_type = CHALLENGE_TYPE_MIDI;
+           } else if (strcmp (value, "text-to-speech") == 0) {
+               category->challenge_type = CHALLENGE_TYPE_TEXT_TO_SPEECH;
            } else {
                fprintf (stderr, "Unknown value for \"challenge\" option \"%s\" at %s:%d\n",
                         value, path, line_count);
                exit (1);
            }
+       } else if (strcmp (name, "repeat") == 0) {
+           if (strcmp (value, "0") == 0) 
+               category->repeat = 0;
+           else
+               category->repeat = 1;
        } else {
            fprintf (stderr, "Unknown option %s at %s:%d\n",
                     name, path, line_count);
@@ -1041,6 +1063,7 @@ mnemon_handle_command (mnemon_t           *mnemon,
     const char *arg;
     int len;
     switch (command[0]) {
+       /* 'h' for histogram */
        case 'h':
        {
            char *category = NULL;
@@ -1059,6 +1082,12 @@ mnemon_handle_command (mnemon_t          *mnemon,
            mnemon_print_histogram (mnemon, category, length);
        }
        break;
+       /* 'r' for repeat */
+        case 'r':
+       {
+           /* Nothing necessary for repeating. */
+       }
+       break;
         default:
            printf ("Unknown command: %s\n", command);
            break;
@@ -1093,13 +1122,11 @@ mnemon_handle_response (mnemon_t        *mnemon,
        (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
         * never been asked. */
        if (item->score == 0) {
            item->score = 1;
            mnemon->unlearned--;
-           mnemon->to_master--;
            printf ("You got it!");
        } else if (item->score < 0) {
            printf ("Yes---just give me %d more.",
@@ -1108,6 +1135,8 @@ mnemon_handle_response (mnemon_t  *mnemon,
            printf ("On your first try, no less!");
        } else {
            printf ("Masterful (%dx).", item->score);
+           if (mnemon->to_master)
+               mnemon->to_master--;
        }
     } else {
        if (! correct)
@@ -1123,12 +1152,13 @@ mnemon_handle_response (mnemon_t        *mnemon,
                printf (" Oops, you knew that, right? (%dx)\n ",
                        item->score);
            mnemon->unlearned++;
-           /* We add three here, (rather than just 2 to track the
-            * change in the item's score below), as an extra
-            * penalty. If the user is forgetting stuff learned
-            * previously, then more time should be spent on mastering
-            * than learning new items. */
-           mnemon->to_master += item->score + 3;
+           /* We increase to_master here as an extra penalty. If the
+            * user is forgetting stuff learned previously, then more
+            * time should be spent on mastering than learning new
+            * items. Note that we only do this during the initial
+            * phase while new items are still being introduced. */
+           if (mnemon->to_introduce)
+               mnemon->to_master++;
            /* We go to -2 to force a little extra reinforcement
             * when re-learning an item, (otherwise, it will often
             * get asked again immediately where it is easy to get
@@ -1136,7 +1166,6 @@ mnemon_handle_response (mnemon_t  *mnemon,
            item->score = -2;
        } else {
            item->score--;
-           mnemon->to_master++;
        }
     }
 
@@ -1182,6 +1211,12 @@ mnemon_show_challenge (mnemon_t *mnemon,
     case CHALLENGE_TYPE_AUDIO:
        program = "play";
        break;
+    case CHALLENGE_TYPE_MIDI:
+       program = "timidity -Os";
+       break;
+    case CHALLENGE_TYPE_TEXT_TO_SPEECH:
+       program = "mnemon-tts";
+       break;
     }
 
     xasprintf (&command, "%s %s/%s >/dev/null 2>&1 &",
@@ -1289,6 +1324,15 @@ mnemon_do_challenges (mnemon_t *mnemon)
                                (start.tv_sec + start.tv_usec / 1e6),
                                category->time_limit);
        free (response);
+
+       /* Replay audio challenges for reinforcement. */
+       if (category->repeat)
+       {
+           mnemon_show_challenge (mnemon, category->challenge_type,
+                                  item->challenge);
+           printf ("%s\n", item->challenge);
+           sleep (2);
+       }
     } while (mnemon->to_introduce ||
             mnemon->unlearned ||
             mnemon->to_master > 0);