The purpose of this assignment is to give you more practice writing functions and programs in Python, and in particular writing code with dictionaries and files.
You should spend at least one hour reading through this handout to make sure you understand what is required, so that you don't waste your time going in circles, or worse yet, hand in something you think is correct and find out later that you misunderstood the specifications. Highlight the handout, scribble on it, and find all the things you're not sure about as soon as possible.
It is probably worth spending at least a day thinking about the assignment before writing code of any sort. Try to think through potential problems to catch them before they appear. This will save hours of frustrating debugging time.
You've been tasked with writing a backend to some gym software that will allow a gym to keep statistics of their users. You will start with no information, and will be passed a filename representing some number of workouts by a user. This may happen several times. In addition, you will be asked to generate and recall information about the workouts you have already loaded.
[day]-[month]-[year]
. This will be the only thing on that line. Following this, there will be an optional line that contains one field: Weight. The Weight will be in the following format:
Weight: [weight]
Weight can be either in lb
or in kg
. Every subsequent line will have the format:
[Exercise Name]: [weight of first set],[reps in first set];[weight of second set],[reps in second set];[. . . .];[weight of last set],[reps in last set]
The exercise name can be any legal sequence of strings. In particular, it will not necessarily be chosen from some set of canonical exercise names. The weight is an integer followed by kg
or lb
. The number of reps is an integer. If an exercise is in a workout, it contains at least one set. Use of kg or lb does not need to be consistent throughout a set. Different exercises may have different numbers of reps. As soon as there is a line of white space, or a date, that represents the ends of information about the workout that was just written. Workouts do not need to be in chronological order.
One person may have multiple workout files, but each date can occur only once across a person's multiple workout files. So multiple people may workout on the same day, but no person will have multiple workouts on the same day. The first workout (first in terms of calendar date)for any person will their weight. If a workout does not contain a weight line, you are to assume that during that workout the person weighed as much as the last previous (according to the calendar) workout in which the person specified a date. An example workout file is here.
You will be responsible for loading a bunch of these files and then returning the information contained in them. However, you will not be responsible solely for regurgitating the information contained within these files. You will also need to generate meta-information contained within them. This means you will need to think carefully about how to design your objects so that you can easily generate this meta-information. You should read the functions you need to generate carefully, and then think about how you want to load data to be able to answer these questions easily.
You need to implement the following functions:
('B', '11-11-2010', 375.0)
(assuming B performed this workout on Nov. 11th of 2010). This function searches across all possible dates. Clarification due to Piazza question: If A bench pressed (100kg, 3), (50kg, 10), on Sep. 21st of 2009 and B bench pressed (75kg, 5), (60kg, 5), (60kg, 5), on Nov. 11th of 2010 this function returns ('A', '21-09-2009', 500.0). ('B', '11-11-2010', 75.0, 50.0)
.break
or continue
statements.
Any functions that do will receive a mark of zero.
We are imposing this restriction (and we have not even taught you these
statements)
because they are very easy to "abuse," resulting in terrible code.
Here is our suggestion. First download the code from a2.py. This is literally just the method stubs. You will be obliged to write docstrings for each function. The first line of each docstring is written for you, because it's unclear that you gain anything through enforced copying and
This program can be broken down into two main aspects. The first is the code that loads files. Note that in order to have the information available after loading the files, you will need to have global variables. The design of your global variables is incredibly important. We will not be running really massive files, so super-efficient solutions are not required. In general, prioritise making your code simple and easy to understand and implement over it being super fast. In particular, it may be easier to call a function even if it is a bit slower than directly computing something.
Note that when a new workout file is loaded, it may change the implicit weights of some people in some of the workouts from previous files. We may load newer workout files before older ones, and so when an older file is loaded, it might change some of the implicit bodyweights. It will always be true that for every member at all points of our testing the earliest workout that you have access to will contain a weight. We may load workout files, test some functions, load more workout files and test the functions again.
Hint: You should probably use a dictionary as your base global variable. It should be nested at least one. A solution uses a dictionary as the base global variable. The values of the base global dictionary are also dictionaries, and the values of these dictionaries are also dictionaries. Notes, that this is not required, but recommended. Another useful thing is to store the date in a format so that when you sort the dates, they get sorted from least recent to most recent. Observe that if you sort the strings you get from the file, this property does not hold. But storing the date in a format that can be easily meaningfully sorted will make this problem much easier.
Questions to keep in mind when designing the data structure and functions: How can one easily get a person's weight for any given workout of theirs? How can one easily get access to a workout given a persons name and date? How can one easily get access to an exercise given a person, name, date and exercise? How do I get the set of results to sort? Was there something useful in exercise 3 for this assignment?
These are the aspects of your work that we will focus on in the marking:
Correctness: Your code should perform as specified. Correctness, as measured by our tests, will count for the largest single portion of your marks.
Docstrings: For each function that you design from scratch,
write a good
docstring
.
(Do not change the docstrings that we have already written for you.)
Make sure that you read the Assignment rules page for some important
rules and guidelines about docstrings.
Internal comments: Within functions, the more complicated parts of your code should also be described using "internal" comments. For this assignment, internal comments will be more important than on assignment 1.
Programming style: Your variable names should be meaningful and your code as simple and clear as possible.
Formatting style: Make sure that you read the Assignment rules page for some important rules and guidelines about formatting your code.
Submit a file named a2.py to markus. Once you have submitted, be sure to check that you have submitted the correct version; new or missing files will not be accepted after the due date.
If you wish to work with a partner, one of you needs to invite the other to be a partner, and then they need to accept the invitation. To invite a partner, navigate to the Assignment 2 page, find "Group Information", and click on "Invite". You will be prompted for the other student's cdf user name; enter it. To accept an invitation, find "Group Information" on the Assignment 2 page, find the invitation listed there, and click on "Join". Note that, when working in a pair, only one person should submit the assignment.
Remember that spelling of filenames, including case, counts. If your file is not named exactly as above, your code will receive zero for correctness.