-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathstudent_manager.py
More file actions
138 lines (115 loc) · 4.08 KB
/
student_manager.py
File metadata and controls
138 lines (115 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
Core StudentHub functionality
"""
from datetime import datetime
from utils import calculate_days_remaining, validate_grade, get_priority_level, save_to_json, load_from_json
class StudentManager:
PERSISTENCE_FILE_NAME = "data.json"
def __init__(self):
self.assignments = []
self.grades = []
def add_assignment(self, title, deadline, subject=None):
"""Add a new assignment"""
assignment = {
'title': title,
'deadline': deadline,
'subject': subject,
'completed': False,
'created_at': datetime.now()
}
self.assignments.append(assignment)
return assignment
def list_assignments(self, show_completed=False):
"""List all assignments"""
if show_completed:
return self.assignments
return [a for a in self.assignments if not a['completed']]
def mark_completed(self, title):
"""Mark an assignment as completed"""
for assignment in self.assignments:
if assignment['title'] == title:
assignment['completed'] = True
return True
return False
def add_grade(self, subject, grade):
"""To check that the grade is integer or not"""
if not isinstance(grade, int):
raise TypeError("Grade must be an integer")
"""Add a grade for a subject"""
if not validate_grade(grade):
raise ValueError("Grade must be between 0 and 100")
self.grades.append({
'subject': subject,
'grade': grade,
'date': datetime.now()
})
def calculate_gpa(self):
"""Calculate GPA from grades"""
if not self.grades:
return 0.0
total = sum(g['grade'] for g in self.grades)
return total / len(self.grades)
def get_upcoming_deadlines(self, days=7):
"""Get assignments due within specified days"""
upcoming = []
for assignment in self.assignments:
if assignment['completed']:
continue
days_left = calculate_days_remaining(assignment['deadline'])
if 0 <= days_left <= days:
upcoming.append({
**assignment,
'days_remaining': days_left,
'priority': get_priority_level(days_left)
})
return sorted(upcoming, key=lambda x: x['days_remaining'])
def dump_manager(self):
"""Dumps data into json file for persistence"""
data = self._ser_object()
save_to_json(data, self.PERSISTENCE_FILE_NAME)
@classmethod
def load_manager(cls):
"""
Load data into the program from persistence file
Returns:
int: status of loading data from file
0 - success
1 - persistence file not found
2 - corrupted persistence file
"""
res = load_from_json(cls.PERSISTENCE_FILE_NAME)
if res["status"] != 0:
status = res.get("status")
return cls(), status
return cls._deser_object(res.get("data")), 0
def get_statistics(self):
"""Get student statistics"""
total_assignments = len(self.assignments)
completed = sum(1 for a in self.assignments if a['completed'])
return {
'total_assignments': total_assignments,
'completed': completed,
'pending': total_assignments - completed,
'gpa': self.calculate_gpa()
}
def _ser_object(self):
"""
Protected method to aggrigate data
Returns:
dict: final data
"""
return {
"Assignments": self.assignments,
"Grades": self.grades
}
@classmethod
def _deser_object(cls, data):
"""
Protected method to load aggregate data
Args:
data: dict - data to be deserialized
"""
manager = cls()
manager.assignments = data.get("Assignments", [])
manager.grades = data.get("Grades", [])
return manager