[+] TT2
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
"""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}
|
||||
Reference in New Issue
Block a user