The purpose of this assignment is to give you practice using dictionaries, reading from text files, and designing larger pieces of code. In assignment 1, you wrote the bodies of small functions which had been planned out for you -- you were given their headers and docstrings. In assignment 2, you had a chance to design your own helper functions. For this assignment, you will design all of the functions. The assignment specifies only what the input and output should be for your program; all of the program design is up to you this time.
You and your partner should spend at least one hour reading through this handout to make sure you understand what is required. Be sure to get any clarification you need as soon as possible, and start working on the assignment, even in little bits, early.
You probably use software like Apple's iPhoto or Windows Photo Gallery to keep track of your digital photographs. These programs allow you to create albums or slideshows from specific photos, based on things like your rating of the photo, when it was taken, or who is in it. For this assignment, you will write a program that allows the user to create a custom slideshow based on the faces, places and events depicted in their pictures.
Your program is designed to be run from a folder that contains a number of picture files, plus a special text file that contains information about those pictures. Your program will read this data, and then interact with the user to create the list of the photos they want to see. In a more realistic program, this interaction would involve a graphical user-interface with buttons and menus and so on. We're not quite ready for that yet, so we'll interact via typing.
Your program should do the following:
os.path
and call function
os.path.exists
, passing it a filename.
It will return a True
iff the file exists.
Your program's correctness will be evaluated by another program, while other aspects that require more judgment will be assessed by a TA. In order for our program to know whether yours works properly or not, you must follow our specifications very carefully, and your input and output must match exactly with what we expect, both in content and format. To be sure that this is the case:
print
statements and
raw_input
statements
must use for all messages and prompts.
You may not print any other outptut to the shell.
(Of course, you will also use media
functions and/or
methods to do your slideshow.)
The picture data file is a plain text file that contains names of picture files, such as "91238.jpg" and data about the contents of the pictures. You will find it easier to understand the formal definition of the file format below if you look at a sample picture data file at the same time.
A picture data file contains one or more sets of the following:
faces
end
places
end
events
end
endpic
Your program must create the following objects as it reads the picture data file:
Your program must consult these data structures, as appropriate, in order to filter the initial list of pictures according to the user's wishes. You may not create any additional objects to store the information from the picture data file.
You will find it easier to understand this description of the filtering process if you look at a sample interaction at the same time.
The user has the option of filtering the full list of image files down to a smaller set, based on the faces, places, and events that they want or don't want included. Here is how that process should work.
In order to simplify your program, however, filtering will be based on exact string equality. Suppose the user wants to filter the list based on a face, they give the name "Catherine", and they want that face included. Then a picture stays in the picture list only if the exact string "catherine" was on the picture's face list. (Notice that the user's input has been converted to lowercase, as mentioned above.) It's not good enough if "cath" or "catherine fairgrieve" was on the picture's face list.
Once filtering is complete, your program must print the pared down list of pictures (that is, the names of the picture files) to the shell. These must be printed with five names per line, separated by a semicolon and a blank. The final name should be followed by a semicolon.
The last thing your program must do is
ask the user whether they want to see a slideshow of their
pared down picture list.
If they do,
first ask them for how many seconds they would like to view each picture.
Then display each picture, one at a time, for that many seconds.
After each picture's display period is over, remove it from display
by calling function media.close
.
There is a simple way to let a period of time elapse in your program:
import a module called time
and call the function
time.sleep
, passing it a number of seconds.
This is your first program where you have the freedom (and responsibility)
to design all of the functions yourself.
A significant part of your grade will be for how well you do this.
Of course, you could write the entire program as a very large
if __name__ == "__main__"
section.
This would be a poor design, however.
You should use functions to divide your program into meaningful
pieces.
One reason for introducing a function is to avoid repeating code. If you find that you need to do the same series of steps more than once, you should define a function once and call it several times instead. This is not the only reason to define functions, however. Functions help to break code into manageable chunks. This will improve the readability of your code and is worth doing even if you only need to call the function once.
Each time you need a new function, take the time to design it. In other words,return
that thing.
def
statement)
You don't have to follow the above process so strictly. You may recognize early on that you are definitely going to need a function for a certain task. You can go ahead and design, write, and test that function before you write the code that needs to use it.
Whatever order you develop the code in, it is extremely wise to test it in small pieces as you go. That way, you are building a big program out of smaller pieces that already work. This is much easier than completing a draft of the whole program and then sitting down to try to make it work. It also leaves you the option of earning some part-marks for correctness if you run out of time before getting the whole program working, because you will at least have some of the functions working.
One extremely good (and disciplined) habit is to design your test cases for each function before you write the function. All you need is the function header and docstring in order to plan your testing. The process of planning it will force to to refine your thinking about how the function should perform in all possible situations. Update your docstring to reflect these refinements, and you will be in a really strong position to write a function that works, as well as code that gets what it expects when it calls your function.
Hint: There will be places in your program where you could end up repeating the same code 3 times, once for each dictionary. Avoid this by making a function that can do the task for any given dictionary.
These are the aspects of your work that we will focus on in the grading:
Correctness: Your code should perform as specified. Correctness, as measured by our tests, will count for the largest single portion of your marks. Remember that the format of your output, not just the content, must be exactly as specified, or your program will be assessed as incorrect.
Program design: Your program should be broken into functions, both to avoid repetitive code, and to make the program easier to use. Each function should have a coherent purpose. Functions should use parameters to get all the information they need from the caller, and should use a return value to give back any relevant information to the caller.
Programming style: Your variables names should be meaningful and your code as simple and clear as possible.
Hand in the file filter.py
, which should
contain your main program and all helper functions that you have written.
Make sure that your program has an if __name__ == "__main__"
section, and includes any import statements that are needed.
It is a good idea to run your program one last time before submitting;
sometimes students make a mistake during last-minute improvements
and submit a program that doesn't run at all.