0

I need help with a weighted grade calculator, i have the bits that i need to calculate the data and the weighted averages. My problem is importing the data and storing it. I think i need to use lists but im just not sure how to separate each entry, I know I can use .split() and i will probably do that. But my real problem is figuring out how to store these values and then write to an output file.

So this is what the .txt file will look like for the input that i am importing to my program with a "open("scores.txt","r")" command

Babbage, Charles
10.0   9.5    8.0  10.0
 9.5  10.0    9.0
85.0  92.0   81.0
Turing, Alan
10.0   8.0    6.0
10.0  10.0    9.0   9.5
90.0  92.0   88.5
Hopper, Grace
10.0  10.0    8.0
10.0  10.0    9.0   9.5
90.0  92.0   88.0
Van Rossum, Guido
 7.5   8.5
 7.5   8.5    6.0   9.0
68.0  81.0   70.0
Backus, John
 9.5   9.5   10.0   8.0   9.5  10.0
 7.5   8.5    6.0   9.0  10.0
99.0  93.0  100.0
Crawley, Bryan
 6.0
 7.5
70.0  60.0   55.5

I tried using s.isdigit and s.isalpha and that didnt really work. 1st line is quizzes, 2nd line is projects, and third is exams. Number of quizzes and exams are arbitrary, the exams will always have three.

Here's what the output needs to look like:

Babbage, Charles      89.4   B
Turing, Alan          91.3   A
Hopper, Grace         92.7   A
Van Rossum, Guido     75.5   C
Backus, John          94.4   A
Crawley, Bryan        63.9   D

Here is what my code looks like now:

quiz_scores = []

while True:
    score = float(input("Quiz #{} ----- ".format(len(quiz_scores)+1)))
    if score == -1:
        break
    quiz_scores.append(score)
quiz_total = sum(quiz_scores) - min(quiz_scores)
if len(quiz_scores)>1:
    quiz_avg =  (quiz_total/((len(quiz_scores))-1)*10)
else:
    quiz_avg = (quiz_total/(len(quiz_scores)*10)

print()

project_scores = []

while True:
    score2 = float(input("Project #{} -- ".format(len(project_scores)+1)))
    if score2 == -1:
        break
    project_scores.append(score2)

project_total = sum(project_scores)
project_avg = (project_total/(len(project_scores))*10)

print()

exam1 = float(input("Exam #1 ----- "))
exam2 = float(input("Exam #2 ----- "))


print()

final = float(input("Final Exam -- "))

average = ((quiz_avg*.15)+(project_avg*.20)+(exam1*.20)+(exam2*.20)+(final*.25))

print("Average ---- %.2f" % average)



if 90 <= average <= 100:
    print("Grade ------- A")
if 80 <= average < 90:
    print("Grade ------- B")
if 70 <= average < 80:
    print("Grade ------- C")
if 60 <= average < 70:
    print("Grade ------- D")
if 0 <= average < 60:
    print("Grade ------- F")

Definitely looking to learn here, not just copy and paste what you comment; so please bear with me if i have some questions for you.

Thank you guys, this community has been very helpful.

JediObiJohn
  • 79
  • 2
  • 8
  • You may find the answers to [**Saving an Object (Data persistence)**](https://stackoverflow.com/questions/4529815/saving-an-object-data-persistence) useful. By using the `pickle` module you can save your lists of data directly to one or more files and read them back in later. – martineau Oct 31 '17 at 04:44

3 Answers3

0

you may want to use .csv instead. By importing csv or pandas, you can save/load data to/from csv files.

see official documents for more details.

Moyan
  • 327
  • 3
  • 8
  • Unfortunately it needs to be a .txt file – JediObiJohn Oct 31 '17 at 04:31
  • this should be a comment, not an answer – 0TTT0 Oct 31 '17 at 04:31
  • you should have just posted it under the comments of his question as it isn't an answer to his question but a suggestion.. no worries :] – 0TTT0 Oct 31 '17 at 04:35
  • But wait im the guy asking the question haha – JediObiJohn Oct 31 '17 at 04:37
  • oh lol i was directing my comment to Moyan! im working on your code right now, its very fun. thanks for the post! – 0TTT0 Oct 31 '17 at 04:48
  • haha thank you for your help, ill edit the post at the bottom with what im working on as well. It really is fun learning about this, i just hate it when i get stuck! Thanks for your help! – JediObiJohn Oct 31 '17 at 05:05
  • ok i am exhausted so im probably going to bed, but i will look out for your response @0TTT0 , thank you for your help! If i respond to your answer and ask you something tomorrow would you be around? – JediObiJohn Oct 31 '17 at 06:31
  • Did you ever come up with anything @0TTT0 ? – JediObiJohn Oct 31 '17 at 15:22
  • will be posting later this afternoon (have work this morning) with some simple code, no imports and just using a dict – 0TTT0 Oct 31 '17 at 16:34
  • Awesome thanks man. Ya i think as long as im using things like this: "file_name = input("Please enter file name: ") open_file = open(file_name,"r") line1 = open_file.readline()" then i will be fine. I just know the main point of the assignment is to input data by opening a file with the format i posted in the original question. Thanks for your help man, looking forward to reading it. – JediObiJohn Oct 31 '17 at 17:15
0

Edit: I have removed the usage of NumPy and Pandas. If you want more detailed or specific answers to your question, you should update your original question or put in the comments.

If you can't choose how your data input looks like before making it, like @martineau suggested, you could do something like this:

# Ordered dictionary will let us add keys to a dictionary {}, but if we
# access the keys, it will retain the order we added them, which is not
# the default behaviour of a normal dict.
from collections import OrderedDict

# Load the file and sequentially add lines for users. You can simplify
# if they always have 3 lines each
with open('scores.txt') as f:

    out_dict = OrderedDict()
    # Load in each line from the file
    for line in f.readlines():

        # remove commas, replace(), strip newline characters '\n', strip();
        # split the line on spaces '81 81 30' -> ['81', '81', '30']
        line_split = [i for i in line.strip().replace(',', '').split(' ') if i != '']

        # From your current format, we know that some lines start with a character when there is a name, or a digit if it is a number
        # float('4') will give 4
        # float('s') will raise a ValueError exception
        #

        try:
            # If we do not raise an exception, we know it is an integer/float
            vals = [float(i) for i in line_split]
            # We can keep adding the values to the last entry in our dictionary, i.e., to the last name we created
            # As we used OrderedDict, we do not have to worry that we will retrieve a random key.
            out_dict[[i for i in out_dict.keys()][-1]].extend(vals)
        except ValueError:
            # So, if we raise an exception, we know it is 'Charles Babbage'
            # A new name is a new key, so put a new key in out_dict, and make the value a list we can keep adding to
            out_dict[line.strip()] = []

Then you can play around with this dictionary however you like. You can also make get_score and get_grade to work as you want, for now I just took the average as I didn't fully understand your intention....

# Some functions to define how the score and grading works
def get_score(scores):
    return sum(scores)/(1.0*len(scores))

def get_grade(score):
    if 90 <= score <= 100:
        return 'A'
    if 80 <= score < 90:
        return 'B'
    if 70 <= score < 80:
        return 'C'
    if 60 <= score < 70:
        return 'D'
    if 0 <= score < 60:
        return 'E'

for key, item in out_dict.items():
    print(key, get_score(item), get_grade(get_score(item)))

The output will look like:

Babbage, Charles 32.4 E
Turing, Alan 33.3 E
Hopper, Grace 33.65 E
Van Rossum, Guido 29.5555555556 E
Backus, John 27.8214285714 E
Crawley, Bryan 39.8 E
jonnybazookatone
  • 2,188
  • 15
  • 21
  • dang, i am not fully sure how this works I was going to use some diagnostic output to track it as i am not familiar with a lot of the functions but it wont even get past import numpy as np – JediObiJohn Oct 31 '17 at 14:10
  • You need numpy installed if you want it to run. I've removed numpy and pandas and put some inline comments to try to help you understand. Ask more specific questions in the comments/OP if you need more guidance. – jonnybazookatone Nov 02 '17 at 09:10
0

Hopefully you can grok what has been done here.. if you have any questions let me know.

gradebook={}
input_name = input("Enter input file:")
output_name = input("Enter input file:")

with open(input_name,"r") as file:
    for line in file:
        if line[0].isalpha():
            gradebook[line.strip()] = {'quizzes':next(file).strip().split(' '), 
                                        'projects':next(file).strip().split(' '), 
                                        'tests':next(file).strip().split(' ')
                                        }
for student, values in gradebook.items():
    quizzes = []
    projects = []
    tests = []
    for category, grades in values.items():
        for grade in grades:
            if grade != '':
                exec("%s.append(float(grade))"% category)
                # ^^^ THIS IS THE SAME AS THE FOLLOWING 
                #if category == 'quizzes':
                #   quizzes.append(float(grade))
                #if category == 'projects':
                #   projects.append(float(grade))
                #if category == 'tests':
                #   tests.append(float(grade))

    quiz_total = sum(quizzes) - min(quizzes)

    if len(quizzes)>1:
        quiz_avg =  (quiz_total/((len(quizzes))-1)*10) 
    else:
        quiz_avg = (quiz_total*10) #no reason to divide by len(quizzes) if it is 1

    project_total = sum(projects)
    project_avg = (project_total/(len(projects))*10)

    exam1 = tests[0]
    exam2 = tests[1]
    final = tests[2]

    average = ((quiz_avg*.15)+(project_avg*.20)+(exam1*.20)+(exam2*.20)+(final*.25))

    if 90 <= average <= 100:
        final_grade = "A"
    if 80 <= average < 90:
        final_grade = "B"
    if 70 <= average < 80:
        final_grade = "C"
    if 60 <= average < 70:
        final_grade = "D"
    if 0 <= average < 60:
        final_grade = "F"

    with open(output_name,"a") as file:
        file.write("{0:20} {1:0.1f} {2:>4}\n".format(student, average, final_grade))

This outputs the following:

Babbage, Charles     89.4    B
Turing, Alan         91.3    A
Hopper, Grace        92.7    A
Van Rossum, Guido    75.5    C
Backus, John         94.3    A
Crawley, Bryan       54.9    F

Not sure why Bryan Crawley's grade is lower than you expected?

0TTT0
  • 1,288
  • 1
  • 13
  • 23
  • Instead of printing the output, could you help me figure out how to send that to a text file called "results.txt" ? – JediObiJohn Nov 01 '17 at 04:38
  • This is awesome man, is there a way to change it to where the user defines what file it is being written to? Heres what i edited the input up top to so the user can specify what they want their file to be called https://imgur.com/a/WRb5q – JediObiJohn Nov 01 '17 at 04:50
  • if that's everything, go ahead and mark the answer accepted by clicking the grey check mark next to the question, it should turn green when you do so.. thanks for the problem, i'm relatively new to python too so the code was fun to write! – 0TTT0 Nov 01 '17 at 04:59
  • it fixes the input title but the output still is stuck at "output.txt". Is there anyway we can make it to where "output_name" is what the output file is called https://imgur.com/a/WRb5q – JediObiJohn Nov 01 '17 at 05:01
  • That's perfect man. I am not familiar with a few of these functions so i might add a comment later on just to get some insight if you ever feel like explaining something further. (wish there was a way to message people on this site.) If not - no worries! seriously thank you, ive been scratching my head over this one all week. Went ahead and marked you with the green check, thanks again. – JediObiJohn Nov 01 '17 at 05:08
  • ugh i think i did something wrong, it's only outputting "Crawley, Bryan 54.9 F" to my results.txt output file now – JediObiJohn Nov 01 '17 at 05:12
  • you have to open it with `"a"` for append and not `"w"` for write otherwise it overwrites it for each loop – 0TTT0 Nov 01 '17 at 05:15
  • changed to "open_output = open(output_name, "a") , and it's still doing the same thing. It seems to be adding the last line each time i run it actually – JediObiJohn Nov 01 '17 at 05:21
  • ok so weird, i closed everything out and opened it back up and its working now lol. Thanks man – JediObiJohn Nov 01 '17 at 05:24
  • Hey man, just wondering. Could you explain the "exam1 = tests[0], exam2 = tests[1], final = tests[2]" That's the only portion i couldnt understand what was happening. Thanks again for all your help @0TTT0 – JediObiJohn Nov 01 '17 at 12:18
  • `tests` is a list with the exam scores in it, so we take them each out individually and assign them to independent variables so that we can reference them when calculating `average` – 0TTT0 Nov 01 '17 at 21:23