Instructions for timeProfiler

(produced at 00:22 a.m. UTC on 2023-09-19)

This task is part of project03 which is due at 23:00 EDT on 2023-09-26.

You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.

You can download the starter code for this task using this link.

You can submit this task using this link.

Put all of your work for this task into the file timeProfiler.py
(you will create this file from scratch)

Armed with Python knowledge from your first two problem sets, you've decided to form a software startup that provides your fellow students with useful programs.

Since time is important to all Wellesley students, you've decided your first program should be a time profiler that helps students calculate how they spend their time during a typical week. The program will ask the user to enter a few pieces of information, and then will display a few calculations about the time spent on various things every week:

  1. Work: This is time spent working for pay.
  2. Sleep: This is the amount of time you spend sleeping each week.
  3. Coursework: This includes time in class plus homework time. You should assume that two hours of homework time are required for every hour in class.
  4. Extra Activities: This includes time spent in organized athletics, music activities, clubs and any other extracurricular activities. Your program will ask the user to name this category.
  5. Free Time: For simplicity, this category encompasses all activities not covered by the other activities above.

When you call your timeProfile function, it should prompt the user to enter information about these activities and display a time profile. We have provided three example executions of the time profiling program that show how your program should behave, and the test_timeProfiler.py starter file can automatically report whether your output is correct, or if not, where the first difference was detected. In each run, text in black is displayed by the program, while text highlighted in blue is entered by the user.

Note that in the example output, each number of hours has been rounded to two decimal places (in some cases Python only shows one because the second is a zero).

Also note that your program should ask the user for the name of the category used to describe the 'everything else' category, and then use that name in the remainder of the program. In the examples below, Latanya chose to use the name 'organizing', Alex chose to use the label 'extracurricular', and Yuting chose to use the name 'fun'. The user of the program gets to decide which name to use to describe that category, and your program incorporates that name into the profile.

In this task, you will write a time profiling Python program timeProfiler.py from scratch in Thonny that has the behavior indicated by the sample executions above. You are also required to define several supporting functions and use them within the timeProfile function.

Your goal is to create a timeProfiler.py program that behaves exactly as indicated by the sample executions provided, and works reasonably on other sample inputs that might be used to test it.

Required Functions

It's possible to write all of your code inside a single timeProfile function and match the example outputs we provided. But such a program would not be elegant, because lots of code would need to be repeated. Instead, you must define each of the following functions individually, and then use them together to write timeProfile.

inputFloat

You will notice that one task performed repeatedly in the examples is to ask the user for some kind of number. However, as you may remember, Python's built-in input function always returns what the user types as a string, and if we want a number, it must be converted. Since this pattern of asking for input and converting it to a (floating point) number happens several times, you must write a function to do that, called inputFloat. inputFloat must accept 1 argument to determine the prompt, and then must call input using that prompt to retrieve a string from the user. Then it must convert that to a floating-point number using float and return the resulting number. These inputFloat examples demonstrate how it should work.

formatHours

If you study the example output you will see that when displaying information about the time spent on different activities, there is a standard format used: a number of hours, rounded to two decimal places, followed by a label like "work hours." As part of the approach to indenting these messages, you must write a formatHours function which has two parameters: a number of hours (as a floating-point number) and a label (as a string). As shown in these formatHours examples, the function must return a string containing the number rounded to two decimal places, plus the label, separated by a single space.

By returning a string, this function will enable other code to call it and store the result in a variable, which will then enable things like measuring the length of that variable.

indentMessage

To get the indentation of the last four lines of output correct, so that all of the bars line up and can be compared, you must define an indentMessage function which takes 2 parameters: a message string, and a target length (an integer). This function will add spaces to the left-hand side of the message it is given, returning a new message whose length (including spaces) is equal to the target length. If the message length already meets or exceeds the target length, zero spaces will be added and the message will be returned as-is.

In timeProfile you will be able to line things up correctly by: 1. First computing a target length equal to the length of longest of your five messages. 2. Then calling indentMessage with that target length on each message to create indented messages whose lengths are the same. These indentMessage examples demonstrate how it must work.

createBar

The last component of the output that we need to assemble is the bars of characters which appear after the colons. Because these bars can only have a whole number of letters in them, we will need to round the amount of time to the nearest integer using the round function before using the * operator to repeat the desired letter. Since this process needs to happen once for each bar, you must create a createBar function which takes two parameters: a letter to repeat and a length value (as a floating-point number). It must round off the length value and then return a string consisting of that many copies of the letter it was given. These createBar examples demonstrate how it must work.

timeProfile

Once you've defined all of the other required functions, you are ready to define timeProfile itself. It will not take any arguments, and must call each of your other functions. To ensure that you are not repeating work done by those other functions, timeProfile must call input exactly twice and it must NOT call round or float itself (the formatHours and createBar functions will handle all of the necessary rounding, and inputFloat will handle type conversion).

It must read inputs from the user and then print out a time profile showing how many hours per week are spent on various tasks, with bars of repeated letters allowing a visual comparison of these values. These timeProfile examples show how it should work.

Click here to show hints about timeProfile

It's good practice to try to figure out timeProfile without consulting these hints, but if you're stuck on how to put things together, here are some hints:

  • These are the general steps that timeProfile will use:

    1. Gather inputs, using both input and inputFloat. Make sure you ask the questions in exactly the order specified, or our automatic tests won't work. You'll need to store the inputs that you gather into variables.
      • In one place, you'll need to use the result from one input as part of the prompt for another question.
    2. Next, you'll need to do some math to create variables whose units are hours-per-week.
      • Several questions ask about other things (like hours-per-day) so you need to convert these.
      • Here is where the assumption that course work involves 2 hours of homework per hour of class comes in.
      • There are 7 * 24 = 168 hours in a week. Subtract from this to figure out the amount of free time.
    3. Once you have hours-per-week variables, you'll need to use the formatHours function to build a message string for each category. After you build these messages, you can measure their lengths.
    4. From the message lengths, you can find the longest using max, and then use that number and the indentMessage function to create indented message variables.
    5. To finish things off, use your hours-per-week variables to create bar strings using createBar, and finally put the bars together with the indented messages and print them out.
  • You may assume that inputs are sensible, and the behavior of your program for nonsensical inputs is unspecified. This means that your program can do anything if an input is nonsensical and still be considered correct. For example, if the number of classes specified is negative, the program could fail with an error message immediately, it could fail after reading in other inputs, it could fail after printing the first line of the output display, or it could even work correctly taking that into account, but all of these would be considered "correct" behavior, because we do not expect the number of classes taken to be negative.

    Here are inputs that are sensible:

    • The name input may be any string, including the empty string.
    • The number of classes is assumed to be a non-negative number (integer or floating point number).
    • The average time in class per week is expected to be a number (integer or floating point number)
    • The number of extracurricular hours per week is expected to be a number (integer or floating point number)
    • The number of hours slept per day is expected to be a number (integer or floating point number)
    • The number of inputted hours or their total sum will not be larger than the total number of hours in a week (168 hours). This would lead to a negative value for the amount of free hours.
    • The 'everything else' category can be any string that is not one of the other category names (i.e, it will not be "work", "sleep", "class", or "free").

Testing

We've provided a test_timeProfile file which has tests for each individual helper function as well as tests of timeProfile itself. These tests will be skipped if you haven't yet defined one of the functions, so you can (and should) run this file each time you finish one of the required functions, and then fix any problems that it reports before moving on to the next function.

Notes

Examples

inputFloat Examples

These examples show how inputFloat should work.

In []:
inputFloat('What is pie? ')
Prints
What is pie? 3.1415926
Out[]:
3.1415926
In []:
inputFloat("What rhymes with 'heaven?' ")
Prints
What rhymes with 'heaven?' 7
Out[]:
7.0
In []:
inputFloat("What's below one? ")
Prints
What's below one? 0.999
Out[]:
0.999

formatHours Examples

These examples show how formatHours should work.

In []:
formatHours(10.0, 'work hours')
Out[]:
'10.0 work hours'
In []:
formatHours(1.111, 'fun hours')
Out[]:
'1.11 fun hours'
In []:
formatHours(9.999, 'free hours')
Out[]:
'10.0 free hours'

indentMessage Examples

These examples show how indentMessage should work.

In []:
indentMessage('hello', 7)
Out[]:
' hello'
In []:
indentMessage('hello', 5)
Out[]:
'hello'
In []:
indentMessage('hi', 5)
Out[]:
' hi'

createBar Examples

These examples show how createBar should work.

In []:
createBar('A', 7)
Out[]:
'AAAAAAA'
In []:
createBar('B', 2.111)
Out[]:
'BB'
In []:
createBar('C', 4.999)
Out[]:
'CCCCC'

timeProfile Examples

These examples show how timeProfile should work.

In []:
timeProfile()
Prints
What is your name? Latanya How many hours do you work each week? 5 How many hours per day do you sleep on average? 6.55 How many classes are you taking this semester? 4 For one class, what is the average time spent in the classroom per week? 3.2 What shall we call the 'everything else' category? organizing How many hours per week do you spend on 'organizing'? 24 Weekly time profile for Latanya: 5.0 work hours: WWWWW 45.85 sleep hours: SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS 38.4 class hours: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 24.0 organizing hours: EEEEEEEEEEEEEEEEEEEEEEEE 54.75 free hours: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
In []:
timeProfile()
Prints
What is your name? Alex How many hours do you work each week? 8.5 How many hours per day do you sleep on average? 6.75 How many classes are you taking this semester? 4 For one class, what is the average time spent in the classroom per week? 3.67 What shall we call the 'everything else' category? extracurricular How many hours per week do you spend on 'extracurricular'? 22.5 Weekly time profile for Alex: 8.5 work hours: WWWWWWWW 47.25 sleep hours: SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS 44.04 class hours: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 22.5 extracurricular hours: EEEEEEEEEEEEEEEEEEEEEE 45.71 free hours: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
In []:
timeProfile()
Prints
What is your name? Yuting How many hours do you work each week? 0 How many hours per day do you sleep on average? 8 How many classes are you taking this semester? 5 For one class, what is the average time spent in the classroom per week? 2.5 What shall we call the 'everything else' category? fun How many hours per week do you spend on 'fun'? 15 Weekly time profile for Yuting: 0.0 work hours: 56.0 sleep hours: SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS 37.5 class hours: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 15.0 fun hours: EEEEEEEEEEEEEEE 59.5 free hours: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

Rubric

Group goals:
 
unknown All functions are documented
Each function you define must include a non-empty documentation string as the very first thing in the function.
 
unknown Do not ignore the results of any fruitful function calls
According to the "Don't waste fruit" principle, every place you call a fruitful function (built-in or custom) you must store the result in a variable, or that function call must be part of a larger expression that uses its return value.
 
unknown Do not create any variables that you never make use of
According to the "Don't waste boxes" principle, every time you create a variable (using = or by defining a parameter for a function) you must also later use that variable as part of another expression. If you need to create a variable that you won't use, it must have the name _, but you should only do this if absolutely necessary.
 
unknown inputFloat must return the correct result
The result returned when your inputFloat function is run must match the solution result.
 
unknown formatHours must return the correct result
The result returned when your formatHours function is run must match the solution result.
 
unknown indentMessage must return the correct result
The result returned when your indentMessage function is run must match the solution result.
 
unknown createBar must return the correct result
The result returned when your createBar function is run must match the solution result.
 
unknown Lines printed by timeProfile are approximately correct.
We will test what is printed when timeProfile is run, given the example inputs for Latanya, Alex, and Yuting.
 
unknown Reported time values are correct for Latanya, Alex, and Yuting inputs.
We will check that the lines printed by timeProfile which start with numbers closely match the correct output.
 
unknown inputFloat must return the correct result
The result returned when your inputFloat function is run must match the solution result.
 
unknown formatHours must return the correct result
The result returned when your formatHours function is run must match the solution result.
 
unknown indentMessage must return the correct result
The result returned when your indentMessage function is run must match the solution result.
 
unknown createBar must return the correct result
The result returned when your createBar function is run must match the solution result.
 
unknown Output from running timeProfile is exactly correct (extra input)
We will test what is printed by timeProfile code, given some new inputs. These inputs will obey the definition of 'sensible inputs' laid out in the instructions.
 
unknown Define inputFloat with 1 parameter
Use def to define inputFloat with 1 parameter
 
unknown Do not call print
Within the definition of inputFloat with 1 parameter, do not call print.
 
unknown Define inputFloat with 1 parameter
Use def to define inputFloat with 1 parameter
 
unknown Call input
Within the definition of inputFloat with 1 parameter, call input in exactly one place.
 
unknown Call float
Within the definition of inputFloat with 1 parameter, call float in at least one place.
 
unknown Use a return statement
Within the definition of inputFloat with 1 parameter, use return _ in at least one place.
 
unknown Define formatHours with 2 parameters
Use def to define formatHours with 2 parameters
 
unknown Do not call print
Within the definition of formatHours with 2 parameters, do not call print.
 
unknown Define formatHours with 2 parameters
Use def to define formatHours with 2 parameters
 
unknown Call round
Within the definition of formatHours with 2 parameters, call round in at least one place.
 
unknown Use a return statement
Within the definition of formatHours with 2 parameters, use return _ in at least one place.
 
unknown Define indentMessage with 2 parameters
Use def to define indentMessage with 2 parameters
 
unknown Do not call print
Within the definition of indentMessage with 2 parameters, do not call print.
 
unknown Define indentMessage with 2 parameters
Use def to define indentMessage with 2 parameters
 
unknown Call len
Within the definition of indentMessage with 2 parameters, call len in at least one place.
 
unknown Use a return statement
Within the definition of indentMessage with 2 parameters, use return _ in at least one place.
 
unknown Define createBar with 2 parameters
Use def to define createBar with 2 parameters
 
unknown Do not call print
Within the definition of createBar with 2 parameters, do not call print.
 
unknown Define createBar with 2 parameters
Use def to define createBar with 2 parameters
 
unknown Call round
Within the definition of createBar with 2 parameters, call round in at least one place.
 
unknown Use a return statement
Within the definition of createBar with 2 parameters, use return _ in at least one place.
 
unknown Define timeProfile with 0 parameters
Use def to define timeProfile with 0 parameters
 
unknown Do not call round
Within the definition of timeProfile with 0 parameters, do not call round.
 
unknown Do not call float
Within the definition of timeProfile with 0 parameters, do not call float.
 
unknown Define timeProfile with 0 parameters
Use def to define timeProfile with 0 parameters
 
unknown Call input
Within the definition of timeProfile with 0 parameters, call input in exactly 2 places.
 
unknown Call inputFloat
Within the definition of timeProfile with 0 parameters, call inputFloat in exactly 5 places.
 
unknown Call formatHours
Within the definition of timeProfile with 0 parameters, call formatHours in at least one place.
 
unknown Call indentMessage
Within the definition of timeProfile with 0 parameters, call indentMessage in at least one place.
 
unknown Call createBar
Within the definition of timeProfile with 0 parameters, call createBar in at least one place.
 
unknown Call print
Within the definition of timeProfile with 0 parameters, call print in at least one place.
 
unknown Do not use a conditional
Do not use an if statement (possibly accompanied by an elif or else block).
 
unknown Do not use any kind of loop
Do not use any kind of loop.