Project 3: Online Mad Libs®

Dan Garcia, 2006-03-10

The scene: a "typical" post-Thanksgiving day in New York City in 1953

Leonard: Give me an adjective...

Roger: clumsy!

...and with that simple interaction, Mad Libs® were born!

Background

Figure 1. Cover of The Original Mad Libs 1, 1974

Many of us as children were taken on seemingly unendurable car rides and thought we'd die of boredom. Let's face it, you can play the ABC game for only so many miles. Then someone would pull out a Mad Libs® book and smiles would erupt on everyone's faces as hilarity ensued. These wonderful word games are part of the fabric of Americana, and have also spurred many imitations and comedic references.

(If this doesn't ring a bell, you should read more about them and play some online to get a feel what they are.)

The Challenge

We would like to create some fun, online Mad Libs®. There is real room for creativity here -- the lexical categories can be as standard as nouns, verbs and adjectives or be as creative as professor's name, canned meat, and favorite Monty Python actor. In general, however, the more general your blanks are, the more creative and hilarious your finished story will be.

We want you to randomly generate one of (at least) 5 different Mad Libs® sentences. That is, you'll generate a web page that asks the user for different blanks (you might ask for a noun, verb and adjective the first time, and a verb, adverb and pronoun the second time, etc.) and then sends a form to a python script which creates a Mad Lib® based on the response. Your randomization has to involve the types of lexical categories, and not just different output sentences with the same categories. E.g., you can't always ask for a noun and a verb and have template sentences that just use those two categories, like:

In the square example from the CGI Programming supplementary notes, you saw how one Python program can generate the HTML form to send data to another Python program which parses the arguments (fields) and squares a number. The clever thing is that these can be the same Python program! This is commonly done to encapsulate all of the common code into one file. How does the program know whether it's called the first time (with no arguments) so it should print the "Welcome to my program! Please give me a verb and a noun..." HTML, and when it's called with the two arguments so it should print "Here is your Mad Lib®: Please don't eat the building. Want to play another? Click here!" HTML.

You already know the answer to this! How did square.cgi get the value from the number? It used the dictionary-like object returned from cgi.FieldStorage(), right? You already know how to query if a value is in a dictionary using in, so just use that to see if there were any arguments passed in.

Example

Here's a sample interaction of our program. We've taken screenshots of the web page it generates.

Figure 2. Welcome screen which asks for three parts of speech. The "Welcome" part of this page is a little lean; you may want to add more text which explains what Mad Libs® are, displays your name, and perhaps include a fun logo.
Figure 3. The page generated after the user clicked "Go" on the previous page. On the bottom of the page is a link to the same URL that generated the page in Figure 2.
Figure 4. The same URL from Figure 2, but the parts of speech it needs is different because of the randomness we've added. When we click "Go", we get...
Figure 5. Our final Mad Libs® result. Words to live by.

Hints

Here are some general tips that may help you in your journey:

  1. Remember, HTML parsers think anything within angled brackets is a special tag it needs to parse. So, if you are trying to print the type of a particular variable (as in type(var) which might return <type 'dict'>), you might notice that nothing prints out. One quick fix is to use repr(), which returns the string representation of an object (type help(repr) for brief documentation) and then replace the angle brackets with square brackets in the string.
    • There's also a handy function called cgi.escape() that converts text to HTML (it replaces all occurrences of the four characters <>&".
    • A more general way of displaying something in HTML is to use pydoc.html.repr, as in:
      import pydoc
      print pydoc.html.repr(whatever)
  2. The point above highlights some of the problems and frustrations you might have with debugging CGI programs. You may find it useful to write a log (a feature provided by by cgitb and described in the CGI Programming supplementary notes) instead of dumping errors to the page itself.
  3. You might notice that you need to pass information about which random Mad Lib® you're playing back to yourself so you can stuff the responses in the right template. If you use type="hidden" in your input form field, you can pass secret messages to yourself that the user won't see (if they don't look at the URL you generate), like which template you're using. E.g., if you wanted to tell yourself you had just asked the user for the types of speech from template #3, you'd generate the following HTML : <input type="hidden" name="Mad_Lib_Number" value="3">
  4. When asking for a VERB, it's usually pretty standard to assume you'll get the infinitive form. Thus, you should generate template sentences that have "to" in front of VERB" in your template.
  5. To differentiate cases where you may ask for multiple instances of the same part of speech (e.g., NOUN), you should probably internally label them NOUN1, NOUN2, NOUN3, etc. If you try the online Mad Libs®, you'll find yourself providing what seems like 15 nouns! Clearly they did something similar to keep track of all the nouns that were given so they could stuff them in the right place in their template...
  6. If you're working from home, you might have to read up on your Apache http server's documentation in order to turn on support for cgi-bin programs. It's configured to be off by default. If you're working with your instructional account, you should have no problems with this.
  7. Just to get a sense of the size of the solution, ours comes in under 50 lines.

Testing

Test each function in your program with enough different inputs to show that it works. When testing a function, print out the input, the expected result, and the actual result.

Extra for Experts

There are a couple of cool features you can add to make your program sing:

Checklist

These are the requirements to meet for project completion.