Python Project

This is a pair assignment worth 40 points

The program should begin with a comment including your names, a brief description of what the program does and information on any help you received on the project.  If it is entirely your own work, say so.  If anyone helped either of you, identify them by name and describe how they helped.  Also identify how you helped others. 

One partner should submit the file or files for your project.  If you have multiple project files, combine them into a zip file.

Note special requirements due to this being a possibly large and open-ended project:  Include a README.txt file that explains how to run your program in detail, with all the steps to get going, in order.  In particular with multiple files, what IS the main program?  You do not need to repeat explicit prompts in your program.  In general make sure you turn in every file you need to run your program.  For instance you have a graphics program and use, turn in  If you have a web project, make sure you turn in the program and all your templates.... An exception is if you need special packages installed (like Python 2.6 + PyGame).  In such a case be sure to mention it in the instructions, including download URL's. In this case with special package download instructions, please talk with me about arranging to demo your project in class or in Adobe Connect.  

In addition, everyone should separately submit a personal file log.txt .  Note this is a little more elaborate than previous log files.  Include in the file

  1. Areas where you received help other than from your partner.  Include from whom (me, TA, which tutor), and the extent.
  2. Roughly how long you worked for the project (including class time)
  3. Briefly, how it went for you, for instance what was the hardest part to get ...
  4. ** Did the setup with plans and parts due earlier help you spread out the work and do it in manageable chunks?
  5. Who your partner was if you had one, or "No partner"  
  6. If you had a partner, give an indication of how things went with your partner.  Was working together a good thing?  If you worked remotely with a partner, how did that go?
This is an open ended assignment.  You can do a graphics program, a dynamic web program, or some other Python program.  Some very different (and increasingly more difficult) possibilities are mentioned below.
If you would like to do something else, read the section on Alternatives at the end.  Some things are feasible and others are not.  You may not have enough experience to know the difference.  Also it is important to find a way to break the project into a sequence of steps where you can check yourself before adding too much.  Particularly if you suggest a unique project, discuss this all with me before you make your written submission of a plan!

Look on the schedule for the dates that incremental work is due.  Steps I, II, and IV all are separate listed assignments.
  1. Plan for a project:  Turn in a plain text file called plan.txt.  No log.  Mention any partnership in the main file plan.txt   If you are going to do a canned topic from below, the project data can be one line.  If you are making up your own thing, please give me enough detail to get an idea of it and to try to figure out how feasible it is.
  2. Outline of steps to be completed and target dates: Turn in a plain text file called outline.txt.  No log.  Mention any partnership in the main file outline.txt   If you want to show off something that does not fit in a plain text file, submit that separately and refer to it in outline.txt.
    1. descriptions of preferably relatively small steps that can be completed and checked individually
    2. dates for the steps to be completed:  The final project is not an assignment to start the evening it is due!
    3. any partner
  3. Display major steps completed - me meeting with you and seeing, probably in class
  4. Final project due

Project Ideas


Code the classic hangman game, where the computer selects a word randomly from a list, and the player guesses letters, with a limit for the number of wrong letter guesses, displayed somehow.  Correct guesses need to be indicated positionally.  For instance for the secret word "program", if the player has correctly guessed nothing, display underscores for all 7 letters:
_ _ _ _ _ _ _
Later if the user has correctly selected r, you should display something like
_ r _ _ r _ _
and then if g is selected,
_ r _ g r _ _
.... This display is the trickiest part of a basic version.

If you want more information on the rules, ask.  Do not look up code on the web.

The basic version is a short program that needs neither the web nor graphics, so you can do it on any kind of computer.  This is not enough for full credit in itself.  See the elaborations.

Possible elaborations after you get a basic text version working: 
A grade of 75% (30) will be given for a program that correctly satisfies the minimum requirements.   Additions are made for elaborations. 

See some useful code on random choices and testing membership is at the end of this page.

A Graphics Game: Find the Hole

The program should use Zelle's graphics.  Use a random number generator  to select a point and a perhaps radius around that point. These determine the target 'hole' and are not revealed to the player.   The user is then permitted to click around on the screen to “find the hole”.  You should show each point the user tries immediately after the click.  Once the user selects a point that is within the chosen radius of the mystery point, the circle should appear.  There should be a message announcing how many steps it took.  Clicking to find the hole should stop after the hole is found. Tthe easiest way to do this is with while loop to drive the repeated search for the hidden circle.  The loop should stop when the hidden circle is located.

Hint:   If the distance between the hidden center and the latest mouse click is less than the radius of your mystery circle, then the circle is "found".  The example  program has a function getShift to calculate the difference (dx, yd) in the coordinates of two points.  You can either directly use or modify getShift to calculate the distance from the Pythagorean Theorem:   (dx*dx + dy*dy)**.5

The basic version is not worth full credit.  Here are some enhancements to the hole finding game:
A grade of 80% (32) will be given for a program that correctly satisfies the minimum requirements.  Better grades will be given to projects that implement one or more enhancements and a nice user interface.  I suggest you write a little bit of the program at a time, and test it after each small feature is added.

Web Mad Lib

Have several files with mad lib format strings in them.  Chose one at random. (See bullet 3 below.)   Dynamically generate and display a web form with all cues and with input fields for the user to fill in. Process the form and show the resulting mad lib.  Go on to a further random madlib....

Here is a progresson of programs going from limited credit to large amounts of extra credit:  
  1. (30 points)Have a single predetermined madlib file and explicitly embed the key questions for that madlib in a form.  This means the user can start from the web form page.  Important detail for later generalization:  For each cue in the form, make the visible label include the cue in a standard pattern, and make the field name attribute be the cue. 
    There are two levels of embedding data into strings here: 
    1. Embedding the madlib choices in the mad lib using a dictionary cue keys and user responses as values.  This is much like in  The whole madlib becomes a single variable to then embed in the whole result web page template
    2. Embedding the mad lib inside a web page.  This is like generating other web pages.  We have used the dictionary **locals().
    Make sure you see the difference and get both parts.
  2. Generalize to allow any mad lib format string, as in  Initially you can choose a specific mad lib file, but as in, the idea is to not have any of the Python code or web page templates have the cues hard coded into them.  Instead, as in, use my getKey function to extract the list of cues from the madlib, and process all the cues in for-loops.  There are two places you need to do this.  Both require a serious understanding of, the CGI process, and for-loops:
    1. (5 more points) Extracting data from the form:  This is actually the second place in the order of execution of the full program, but if you made the field names match the cues in the first part, you can write and test this part next.  To know what data to extract from the form, extract the list of keys from the madlib format file, and then read the values for those keys from the form input. In, the user was queried and then dictionary entries were made.  In this case you still want to make the same sort of dictionary entries, but the data comes from the form, rather than keyboard input.   You use a cue both to access a piece of data from the form and as a key to place that data in your dictionary.
    2. (10 more points) Getting the cues into the inital form:  For the more general version, the form cannot be a fixed page; it must be generated dynamically to include all the proper cues for the particular madlib file chosen.  You must generate the page from a CGI script.  Look at the source code of the html for the form in step 1(if you followed my suggestions), and see the pattern in the sections that present a single text field per key.  Each such part can be created by embedding a cue into a format string based on the html source code for one entry.  You can copy one entry out of the source for the form for part 1.  You can loop through all the cues and create a list of all the entries with the proper cues.  You can combine a list of strings as you did in the exercise, or you can look at the optional section on the string method join.  A similar construction is done in the advanced example program pizza.cgi for the radio button lines and the check box lines.

      For both part a and part b you need to have many of the same utility functions.  You can have two scripts with much duplicated code, or both parts can be in one CGI script if you provide information to distinguish the two situations.  An obvious choice is to have a hidden variable put in the form that states the madlib file name.  If the cgi program starts without a key associated with such a file name, then the initial form still needs to be created (code of part b), and it needs to include a hidden variable like madlibFile with the value of the madlib file name.   If the script runs when the hidden variable is there, then you know what mad lib template file was used, and have data from a form and can display the madlib with substitutions (code from part a).

      Part b is critical to getting at least full credit.  You can write small separate test programs to get the logic. Given a list of cues, generate a section of a form looking for values.
  3. (2 more points)  This part is independent of the later elaborations listed: include it or not.  It does give a better flow to the cues in the entry form:  Modify the last line of the function getKeys as in the Unique List Exercise.
  4. (2 more points)  Select the mad lib format file at random in the inital cgi program (part b above).  If you have a list aList of madlib filenames, then you can import the random module and use random.shuffle(aList) to mutate the list into a random order.  Then aList.pop() returns the last element, which will be random, because of the shuffle.  See the example in the section below, on random choices from a list.
  5. (10 more points)  After the user sees a completed madlib let the user click to go on to a mad lib form for a different random madlib.  When the user has done all the madlibs, you could tell the user that there are no more madlibs available.  A good way to accomplish this is to make another hidden variable be the remaining list of madlib file names, saved after they were shuffled and the latest file was popped out.  Since the variables must be strings, you need some of the string methods that we skipped in Chapter 2, like split and join, or find with slicing.  You could also set things up to only have one hidden variable if it includes all the remaining madlib file names and the one you are working on at the moment.  
  6. (10 more points) An even greater elaboration would be to allow the user to contribute madlib format strings, and save these to files, and store
    the list of all available madlib names in a separate master file, and shuffle that list when people start in on their first mad lib.

Elaborated Pizza Web Program

Elaborate the pizza order web site in Tutorial section 4.3.5.  There are two levels of elaboration:
  1. (40 points) Rather than hard-coding in pizza.cgi the prices for the basic pizza and for a topping in the different sizes, store the prices in a file and generate the user form from this file.  Have the owner page include a form to allow the prices to be changed, submitted, and remembered in the updated file.  
  2. (15 points extra credit) Similarly allow the owner to change the list of toppings available.  Store updated data in a file (the same file as above or another).  In the owner form it is probably easiest to just have an editable, comma-separated list of entries for toppings.  (Read the parts of Chapter 2 that we skipped.)   This change then should change the list of toppings to choose from in the order form.
You can choose the file format(s).  (Discuss it with me.)   Read the section below on further file methods. 

The manager form should still show the already coded list of past orders.  If the manager form is submitted, store the new prices in your separate file before you go back to the customer order form.  Unlike in pizza.cgi, you will have new price data to display. 

Be sure to discuss with me the format of your data files and  the overall flow of the code.  It is likely easiest to have just one cgi file, since many parts are used in several steps.  You will need hidden variables in your forms to indicate which step is next, since there is different processing after user entry and form owner entry of data.  Reference the hidden variable value to see what section of your code to do.

Here are some parts you could break out of the main project idea.  You could make them consecutive additions to the final program, or test the logic initially in separate programs done in any order: 

Alternatives ....

Are these too lame or canned or not your style?  Suggest something different to me!  You can start by discussing it orally with me, but before final approval, make a written specification for yourself and me, about as specific as what is given for the problems above.  The specification is due as stated in the schedule.  I am more likely to accept a proposal if it includes a new use of a while-loop or for-loop.  Just a a long fixed sequence of steps, even with if statements, is not likely to be accepted.

New Useful Code Ideas

Here are some comments about particular situations that might be of use:

Random choices from a list

>>> import random
>>> aList = ['a', 'bb', 'ccc', 'dddd']
>>> random.shuffle(aList)
>>> aList
['ccc', 'a', 'dddd', 'bb']
>>> entry = aList.pop()
>>> entry
>>> aList
['ccc', 'a', 'dddd']

So with shuffle and pop you can get random choices, and each time you pop from the list, you get a different element.

Testing membership in a sequence

A brief reference was made to the operator initem in seq is true if item  is in the sequence seq, where the sequence can be a string (a sequence of letters) or a list.  Example:

>>> charseq = 'acxz'
>>> 'c' in charseq
>>> 'b' in charseq
>>> nums = [2, 7, 11]
>>> 7 in nums

More discussion supports the Unique List Exercise.

Further file reading operations

Thus far you were only given the method to read a whole file at a time.  You may also read a single line at a time with the file method readline().  A line includes its final newline, but you can use the string method strip() to strip off all the white space from both ends, including the newline.  Example:

infile = open('datafile.txt')
line = infile.readline()
print('line 1 is with whitespace removed from the ends: ', line.strip())   
line = infile.readline()
print('line 2 is with whitespace removed from the ends: ', line.strip())  

(You can also remove the final newline using the slice notation from the optional sections of Chapter 2:  line[:-1].)

If you are converting a line with the text of a single number to a float with the float constructor, the newline does not matter, since white space is automatically stripped in the conversion.  If datafile has a first line like 5.25, then the following code would read it and convert it to a float:

infile = open('datafile.txt')
line = infile.readline()
val = float(line)

Fancy cgi programs with multiple calls to cgi scripts:

In a console Python application you might have something like:

s = input("Enter ....')
# process s
print(....)  # something using s

t = input("Enter ....')
# process with BOTH s ans t
print (....)  # something based on both s and t...

In a web based situation it is more complicated, because the server does not automatically remember the data from an earlier server call.  You would need something more like this:

#Start with cgi script that works at multiple stages of the input/output sequence:
s = form.getFirst('s', '')
t = form.getFirst('t', '')
# know where you are by how many of your variables have been defined
if s == '': 
    # ... print initial form looking for s value
    # for use in the next case....
elif t == '':
    # ... produce page USING the value of s
    # and also including a form REQUESTING t,

    # AND include in the form a hidden variable 's'
    #    set to the current value of Python variable s
    #    (using template substitution),
    #    for use in the next case, with the new t....

    #  ... generate page using s and t

This shows how to use a couple of pages in sequence.  More elif's and more hidden variables needed for you to have a longer sequence of interchanges, each adding more data to be remembered....