Files
Hykilpikonna 44a4c9bbe5 [+] TT2
2021-12-08 16:45:25 -05:00

192 lines
7.7 KiB
Python

"""CSC110 Fall 2021: Term Test 2, Question 3 (Object Oriented Design)
Module Description
==================
This module contains instructions for this question. There are TWO
parts of this question, labelled "Part (a)", "Part (b)", etc.
The comments in this file contain instructions on how to complete each part,
so please read those comments carefully.
SUBMIT THIS FILE FOR GRADING!
Copyright and Usage Information
===============================
This file is provided solely for the personal and private use of students
taking CSC110 at the University of Toronto St. George campus. All forms of
distribution of this code, whether as given or with any changes, are
expressly prohibited. For more information on copyright for CSC110 materials,
please consult our Course Syllabus.
This file is Copyright (c) 2021 Mario Badr and Tom Fairgrieve.
"""
from dataclasses import dataclass
###################################################################################################
# Modelling a Problem Domain
###################################################################################################
# In this question, you will model a new problem domain by designing classes in a similar style to
# the food delivery system we studied in lecture.
###################################################################################################
# Description of the Problem Domain
###################################################################################################
# Your client is the University of Toronto. They want new software to manage the grades of their
# students. The grade system will store:
# 1. GRADES that each have the course id (e.g., 'CSC110Y'), term id (e.g., '20219'), and score in
# the course (i.e., an integer ranging from 0 to 100, inclusive).
# 2. STUDENTS that each have a utorid (e.g., 'astudent') and a collection of grades.
###################################################################################################
# Part (a) - Entity data classes
###################################################################################################
# Your first task is to complete the two data classes below, which represent the two main entities
# in our computational model. Read the provided docstrings and use them to complete each data class
# body.
#
# Do NOT add any additional instance attributes or change the class docstring.
# You do NOT need to add any representation invariants or doctest examples.
@dataclass
class Grade:
"""A grade on Acorn.
Instance Attributes:
- course: the course (e.g., 'CSC110Y1') this grade was achieved in.
- term: the term (e.g., '20219') this grade was achieved in.
- score: an integer representing the grade achieved.
"""
course: str
term: str
score: int
@dataclass
class Student:
"""A student who can have courses grades on acorn.
Instance Attributes:
- utorid: the utorid of this student
- grades: a dictionary mapping a course (e.g., 'CSC110Y1') to the student's Grade in that
course.
"""
utorid: str
grades: dict[str, Grade]
###############################################################################
# Part (b) - Manager class
###############################################################################
# The class below is responsible for keeping track of all instances of the entities in our
# model and performing mutating operations on them.
#
# Read through the class and implement the methods that have empty bodies.
# Do NOT change anything else in the class (attributes, methods that we have implemented).
class AcornSystem:
"""A class that tracks students and their grades."""
# Private Instance Attributes:
# - _students: a dictionary mapping utorids to Students
def __init__(self, initial_students: list[Student]) -> None:
"""Initialize a new AcornSystem, adding every student in initial_students to this system.
Precondition:
- Every student in initial_students has a unique utorid
"""
self._students = {}
for student in initial_students:
self._students[student.utorid] = student
def student_count(self) -> int:
"""Return the number of students in this system."""
return len(self._students)
def add_grade(self, utorid: str, grade: Grade) -> bool:
"""Add grade to the student with utorid and return whether the grade was added successfully.
Do not add grade if the student with utorid already has a grade assigned for that course.
Preconditions:
- A student with utorid exists in this system
"""
student = self._students[utorid]
if grade.course in student.grades:
return False
else:
student.grades[grade.course] = grade
return True
def get_grades(self, utorid: str, term: str) -> list[tuple[str, int]]:
"""Return a list of tuples of the courses and scores that the student with utorid achieved
in term.
Preconditions:
- A student with utorid exists in this system
- The student in this system with utorid has a grade for course
>>> acorn_system = AcornSystem([Student('astudent', {})])
>>> acorn_system.add_grade('astudent', Grade('CLA204H1', '20209', 76))
True
>>> acorn_system.get_grades('astudent', '20209')
[('CLA204H1', 76)]
"""
return [(g.course, g.score) for g in self._students[utorid].grades.values()
if g.term == term]
def amend_grades(self, utorid: str, amendments: dict[str, int]) -> int:
"""Update the grades for the student with utorid based on the amendments, which maps courses
to the amended score.
Return the number of successful amendments made. An amendment is not successful if the
student has no grade on record for the course. No mutation should occur for students who
have no grade on record for course.
Preconditions:
- A student with utorid exists in this system
>>> acorn_system = AcornSystem([Student('astudent', {})])
>>> acorn_system.add_grade('astudent', Grade('CLA204H1', '20209', 76))
True
>>> acorn_system.amend_grades('astudent', {'CLA204H1': 80})
1
>>> acorn_system.get_grades('astudent', '20209')
[('CLA204H1', 80)]
"""
grades = self._students[utorid].grades
count = 0
for course in amendments:
if course in grades:
grades[course].score = amendments[course]
count += 1
return count
def calculate_averages(self, utorids: list[str]) -> dict[str, float]:
"""Return a dictionary mapping a student's utorid to the average grade they achieved for
all courses completed.
Preconditions:
- Every utorid in amendments is a student in this system
>>> acorn_system = AcornSystem([Student('astudent', {}), Student('bstudent', {})])
>>> acorn_system.add_grade('astudent', Grade('CLA204H1', '20209', 76))
True
>>> acorn_system.calculate_averages(['astudent'])
{'astudent': 76.0}
>>> acorn_system.add_grade('astudent', Grade('CLA205H1', '20219', 98))
True
>>> acorn_system.calculate_averages(['astudent'])
{'astudent': 87.0}
>>> acorn_system.add_grade('bstudent', Grade('CLA205H1', '20219', 98))
True
>>> temp = acorn_system.calculate_averages(['astudent', 'bstudent'])
>>> temp == {'astudent': 87.0, 'bstudent': 98.0}
True
"""
return {u: sum(g.score for g in self._students[u].grades.values())
/ len(self._students[u].grades) for u in utorids}