Project 0 - Grade Calculator
Reminder: For all assignments, BEFORE you start coding, READ THROUGH THE ENTIRE SPECIFICATION and think through at a high level how your full solution will look. Then start coding.
Due by 11:59pm on February 5, 2025
Objectives
- Practice basic Python Syntax
- Understand exactly how your grade is calculated in CS 111
- Build a simple tool to do that calculation for any grade data.
Introduction
In this initial project, you’ll build a small tool that you can use to determine your current grade in the class.
The program will read a file containing all of your assignment grades and then compute your current grade based on the assignment completed and the grading policy in the Syllabus. You should re-familiarize yourself with the grading policy before continuing on.
Program Specification
The program should prompt the user for an input file that contains the grade data. The file format is given below and an example file is provided in the starter files for this project.
The program should then read in all of the grades for the labs, homework assignments, projects and exams provided in the file and calculate a grade for the student based on the submitted assignments and the grading policy specified in the syllabus.
Once the grade is calculated, the program should print out a message indicating the student’s percentages in each category (Labs, Homework, etc.). It should then display the student’s overall percentage and letter grade in the class and then exit.
Sample execution
A sample run of the program might look like this:
> python project0.py
Please enter the grade data filename: grades.dat
Here are the student's grades:
Category Points Percentage
Labs: 174/200 87.0%
Homework: 279/300 93.0%
Projects: 196/200 98.0%
Midterm 1: 35/40 87.5%
Midterm 2: 37/40 92.5%
Final: 68/70 97.1%
The overall grade in the class is: A (93.58%).
>
Sample input file
The input file contains one line per assignment with each line being a comma separated list containing the assignment name and the score. The format of a single line looks like this:
<assignment name>, <score>
The assignment names are of the form:
<type>NN
where type is one of the following:
Lab
Homework
Project
Midterm
Final
FreeCoding
and the NN
after the type is the assignment number. Note that the Final and FreeCoding assignments do NOT have a number after them.
Additionally, the file may contain comments and blank lines. These lines should be ignored by your program. Comment lines always begin with a pound sign (#
).
# This is a comment line
A complete grade file (e.g. grades.dat
) with no scores might look like this:
# Labs
Lab00, 0
Lab01, 0
Lab02, 0
Lab03, 0
Lab04, 0
Lab05, 0
Lab06, 0
Lab07, 0
Lab08, 0
Lab09, 0
Lab10, 0
Lab11, 0
Lab12, 0
Lab13, 0
Lab14, 0
Lab15, 0
Lab16, 0
Lab17, 0
Lab18, 0
Lab19, 0
Lab20, 0
Lab21, 0
Lab22, 0
Lab23, 0
# Homework
Homework0, 0
Homework1, 0
Homework2, 0
Homework3, 0
Homework4, 0
Homework5, 0
Homework6, 0
Homework7, 0
# Projects
Project0, 0
Project1, 0
Project2, 0
Project3, 0
Project4, 0
FreeCoding, 0
# Exams
Midterm1, 0
Midterm2, 0
Final, 0
Calculating the grades
When calculating the grades, you should calculate the percentages for each category based on the number of items listed in the file. For example if there are 3 project scores provided, you would calculate the percentage for projects by adding up the 3 project scores and then dividing by the maximum points possible for 3 projects (3 projects * 100 points per project = 300 points). The points possible for each assignment are given in the following section.
Remember that for some of the categories, we drop the lowest one or two grades. Don’t forget to drop those grades when summing the totals and reducing the maximum points by the correct amount.
Assignment values
The assignments have the following point values:
Assignment | Points | Weight |
---|---|---|
Labs | 20 | 10% |
Homework | 50 | 15% |
Projects (including Free Coding) | 100 | 25% |
Midterms | 40 | 15% each |
Final | 70 | 20% |
Final grade
To calculate final grade, multiply the percentage score in each category by that categories weight to get the weighted score for the category. Then add up all the weighted scores to get the final grade.
For example if the student had a total of 117 points for 6 labs, the lab percentage would be 97.5%. The lab category weight is 10% so we would multiply that 97.5% by 0.1 (10%) to get a weighted lab score of 9.75%.
We do this for each category and the sum of the weighted grades gives us the student’s final grade percentage. We can then look up that percentage in the table on the syllabus to get the final letter grade.
Note: Since the calculator can be used to compute grades before everything is submitted, you will also need to do an additional weighting if categories are missing.
This is done by dividing the summed weighted percentages by the fraction of the grade these represent. This is best illustrated via example
Let’s say you are calculating grades and have the following category percentages:
- Labs: 93%
- Homework: 87%
- Projects: 91%
- Midterm 1: 96%
but you don’t have grades yet for Midterm 2 or the Final. You would calculate the weighted sum of the categories you do have:
Category | Percentage | Weighted Percentage |
---|---|---|
Labs | 93% | 9.3% |
Homework | 87% | 13.05% |
Projects | 91% | 22.75% |
Midterm 1 | 96% | 14.4% |
Total | 59.5% |
These categories only represent 65% of the total grade (10% Labs + 15% Homework + 25% Projects + 15% Midterm 1 = 65%). To account for that, we divide the total percentage (in this case 59.5%) by the fraction of the total grade represented (in this case 65% => 0.65). So the final grade would be 59.5%/0.65 = 91.5%, an A-.
Required output
There are certain parts of the output that the auto-grader will be looking for that you need to get correct to get full credit:
Order of category output
Your output must print out the categories in the order shown in the sample output above. If there are no scores for a category, it should not be printed but if there are scores, they should be printed in the order shown.
Category points and percentages
For each category (Labs, Homework, etc) you must print out the category name, the total points received, total points possible and the percentage for that category.
- The total point received and total points possible should be separate by a forward slash (
/
) - The percentages should be displayed with one digit after the decimal point and the percent sign (
%
) - You will not be graded on the remaining whitespace or symbols on the line but remember it should be readable by the person running the program.
Final grade
The final grade line should be printed exactly as show with the initial text of
The overall grade in the class is:
followed by the letter grade and then the percentage in parentheses. The percentage should be displayed to two decimal places.
Part 1 - Getting Started
Now that you’ve read the entire specification and understand what you should be doing, let’s get everything set up and start coding.
To get started on this homework you should download project00.zip and extract the contents into a new directory. The contents of the file are:
- grade_calculator.py - this is the file you will edit and turn in for grading test_grade_calculator.py - this is a test file you can use to verify that your code is running correctly. This is the exact test script that the autograder will run when you submit your code. test_files directory - This directory contains the expected output for the test script annotated for the test to evaluate. You can look at these files if you get stumped but be aware that they contain extra code that you should not be outputting.
Once you’ve extracted the files, open the directory as a new project in your IDE. Then verify that you can run the test_grade_calculator.py file. If you set up your environment properly during Lab 00, it should run. All the tests will fail as your grade_calculator.py file is empty, but as long as the tests ran you are good to go. If you get a “Traceback” error, something isn’t working and you should check with a TA to get your environment set up correctly.
Part 2 - Implementation
In this part, you will write the code for the program. In this homework, we walk you through the steps, but you should have a good idea of how to write the code for each part already based on the specification above. The tasks below model the concepts of Stepwise refinement and incremental development which we’ve now talked about in lecture.
Task 1 - Get the grade data filename
Homework 1 just used a set filename coded into the program for the file it was supposed to read in. For this project, you’ll prompt the user for the filename to read. This will allow you (and the auto-grader) to use different input files without having to rename each one.
Use Python’s input()
function to prompt the use to input the grade data file’s name and store that in the program. You can use any prompt you want but it should be clear to the user what you are asking for.
Task 2 - Read the Grade Data
Now that you have the filename, you need to open the file and read in the data. Before you start coding, take a moment and think about what you need to do. This is a chance to practice the Stepwise Refinement we talked about in class. How do you break the larger task - Read the Grade Data - into smaller subtasks that accomplish the goal.
Some questions to consider:
- How are you going to store the data in your program?
- How do you read a single line of data?
- How do you determine if a line in the file is a comment or blank and should be skipped?
- How are you going to decide which category a given grade goes into?
Once you come up with a plan, implement it. Read the given file and store the grades in the respective categories.
Task 3 - Initial Output
At this point we probably want to check to see if we have good data in our program. We can do that by implementing an initial version of the output. For now, let’s just print out the categories and sum of all the points in that category along with the total points possible. In doing this, we can implement to logic necessary to only print categories we have scores for. We can come back and add the percentage information later.
Again, take a moment to think about the problem you’re trying to solve:
- With the data you stored in Task 2, how do you get the total points scored?
- How do you get the total points possible?
- With the data you stored in Task 2, how to you determine if a category should be displayed or not?
Now that you’ve answered those questions for yourself, implement your solution and test it. Create a input file that you can use for testing, run your program using that file and see what comes out. Or you can use the grades files in the test_files directory. Is it what you expect? Are only the categories of assignments in the input file printed? Do the numbers look correct? What do you need to fix (if anything)?
Task 4 - Refactoring
Refactoring is a process where you look at your code and clean it up. This could range from changing names to make it more readable, to making the code more efficient, to removing duplicated code by creating functions to hold the code and calling that function where the duplicated code used to be, and so forth.
Refactoring doesn’t change the output or operation of your program, but it makes it easier to read, understand, maintain, and extend. This is something you should do all the time you are writing code. We’ll call it out in early projects, but you should get in the habit of doing it every time you add or modify your program.
Take a few minutes and look at the code you wrote. Is there any way you can improve it? Make those changes and rerun it to make sure it is still working.
Task 5 - Calculating Category Percentages
Now it’s time to calculate the category percentages. This should be fairly straightforward since we have all the data and even summed up the earned points and points possible in Task 3.
However, we need to account for the dropped grades. Remember we drop the two lowest lab grades and one lowest homework grade from the grade calculation. (If you don’t remember go reread the Syllabus.)
Go back and modify your code that added up the points scored and calculated the points possible to drop these low scores.
- How do you determine the lowest scores in a category?
- How do you do the sum (and points possible calculation) to not include those?
- This is a potential refactoring point. You may realize there might be a better way to store the data to make this easier. If so, go ahead and make that change. This is a normal and usual process in software development.
Once you have the updated total points and points possible accounting for dropped grades, compute the percentage for that category. Then update your print routine to add printing the percentage on the category’s line. (Don’t forget that the percentage should be printed with one digit after the decimal place.)
This is a good time to try running the pytests. They won’t pass as you don’t have the final grades calculated but the test should only show failures on that part of the output. If there are failures earlier, you should track down the bugs and fix them now.
Task 6 - Final Grade
Now that you have the category percentages, it’s time to compute the final grade. This is a good time to review the specification for that part of the problem to refresh your memory.
Again, spend some time thinking about how you want to implement this before you dive into coding:
- How do you determine if all the categories have scores?
- How do you determine the weighting percentages for a category?
- How do you determine what fraction to weight the total calculated score with based on missing categories?
- One you have final percentage, how do you get the letter grade?
Once you have your plan, implement it and print out the final letter grade and percentage. (Don’t forget that there are specific formatting requirements for this output.)
Task 7 - Run the tests
You code should be working. Run the provided pytests (if you haven’t already) to verify that everything works. If you are getting errors, figure out what is wrong and fix it.
Task 8 - Final Refactor
Take a final look at your code with an eye to refactoring. Is there anything you can do to make it cleaner, easier to understand, and remove redundancy? If so make those changes.
Turn in your work
Congratulations, you’ve now created a small tool that you can use to calculate your grade in the class at any point.
Be sure to do a final test of your project before submitting to make sure everything is working:
python -m pytest test_grade_calculator.py
or
pytest test_grade_calculator.py
You shouldn’t be getting any errors
You’ll submit your grade_calculator.py
file on Canvas via Gradescope where it will be checked via the auto grader.