In: Computer Science
In this problem, we'll write a Python module that defines two things publicly.
Student = namedtuple('Student', ['scores', 'grade'])
The inputs
The first parameter to your function is the path to a file containing score information, but the interesting thing about it is the format of that information, which we'll need to agree on. What you'll expect is a text file in which each line of text represents one student's information. The first thing you'll see on each line is the student's UCInetID (i.e., an identifier that's unique for each student); after that will be a sequence of numbers that are separated by at least one space, which are that student's raw scores. Any line of text consisting only of spaces, or any line whose first non-space character is a # is to be ignored. Note that it is possible for a student to have no scores.
The second parameter to your function is a dictionary where the keys are letter grades and the values are tuples specifying the range of total scores that would lead to that letter grade. A tuple containing only one value would mean "The given score or anything higher," while a tuple containing two values would mean "Any score that's greater than or equal to the first of these, but is less than the second of these." For example, if the dictionary looked like this:
{'A': (600, ), 'B': (500, 600), 'C': (400, 500), 'D': (300, 400), 'F': (0, 300)}
then we'd expect any student scoring at least 600 points total would receive a grade of A, any student scoring at least 500 points but less than 600 would receive a B, and so on. Don't assume that the letter grades will always be A, B, C, D, and F, or even that they'll always be a single letter. It is expected that the ranges of scores will not overlap; if they do, your function can output any grade that matches (i.e., if 17 points is either a B or a C, you can return either grade for a student in that case).
The output
Your function will return a dictionary where the keys are the UCInetIDs of students who are listed in the file, and where the corresponding values are Student namedtuples with scores being a list of the student's scores (in the order listed on the corresponding line of the file) and grade being the student's grade.
Note that grades are calculated by determining the sum of all of a student's raw scores (i.e., there is no weighting scheme that makes one assignment worth more than another, which is different from the actual grading formula used in this course) and comparing it to the given grade ranges. If the total score is not in any of the given grade ranges, the student's score should be specified as the Python value None.
If the file cannot be opened or it cannot be read to completion, the function should raise an exception; it's not important what kind of exception it is, but the file should be closed in any circumstance in which it was opened successfully.
An example
Suppose that you had a file called scores.txt in the same directory as your problem3.py file, in which the following text appeared.
# Alex has work to do, but is improving thornton 30 40 50 60 70 80 90 # Boo is perfect, as usual boo 100 100 100 100 100 100 100 # Student that submitted no work; total score is 0 didnothing
Here's how your function should behave, given that file.
>>> grade_ranges = {'A': (600, ), 'B': (500, 600), 'C': (400, 500), 'D': (300, 400), 'F': (0, 300)} >>> build_grade_report(Path('scores.txt'), grade_ranges) {'thornton': Student(scores=[30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0], grade='C'), 'boo': Student(scores=[100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0], grade='A'), 'didnothing': Student(scores=[], grade='F')}
Note: Done accordingly. Please comment for any problem. Please Uprate. Thanks. Please indent the code according to code screenshot
Code:
# -*- coding: utf-8 -*-
"""
Created on Sat Oct 31 10:37:33 2020
@author: Faraz
"""
from collections import namedtuple
from os import path
#creating named tuple
Student = namedtuple('Student', ['scores', 'grade'])
def build_grade_report(pathOfFile, ranges):
#checking if path is valid file name
if path.isfile(pathOfFile):
#opening file to read
file1 = open(pathOfFile, 'r')
#reading all lines
Lines = file1.readlines()
#output dictionary
output={}
#looping over each line
for line in Lines:
# Any line of text consisting only of spaces, or any line whose
first non-space character is a # is to be ignored
if line.strip()!='' and ((not '#' in line) or line.index('
')<line.index('#')):
#splitting by space
splitted=line.split(' ');
#getting id
UCInetID=splitted[0]
#for scores
score=[]
#for total score
totalScore=0
#if none criterion matches
gradeOfStud=None
#looping over each score
for i in range(1,len(splitted)):
score.append(float(splitted[i]))
#creating total score
totalScore=totalScore+float(splitted[i])
#looping to get grade
for grade in ranges:
#if tuple has one value only
if len(ranges[grade]) ==1 and
totalScore>=ranges[grade][0]:
gradeOfStud=grade
break
else:
if(totalScore>=ranges[grade][0] and
totalScore<ranges[grade][1]):
gradeOfStud=grade
break
#setting named tuple
S=Student(score,gradeOfStud)
#setting ouput for that student
output[UCInetID]=S
#returning ouput
return output
else:#exception for file
raise Exception("Please give valid file path")
#testing
grade_ranges = {'A': (600, ), 'B': (500, 600), 'C': (400, 500),
'D': (300, 400), 'F': (0, 300)}
print(build_grade_report('scores.txt',grade_ranges))
Code screenshot:
Output: