def __init__(self, file_name): """ Repository for students using persistent storage powered by json text files. :param file_name: string representing the location of the students.json """ StudentRepo.__init__(self) self.file_name = file_name file = open(self.file_name, "r") for obj in json.load(file): self.add_student(Student(obj["sid"], obj["name"])) file.close()
def __init__(self, file_name): """ Repository for students using persistent storage powered by csv text files. :param file_name: string representing the location of the students.csv """ StudentRepo.__init__(self) self.file_name = file_name file = open(self.file_name, "r") for line in file.readlines(): line = line.strip(" \n") stuff = line.split(",") self.add_student(Student(int(stuff[0]), stuff[1])) file.close()
def __init__(self, student_repo=None, discipline_repo=None, grade_repo=None): self._student_repo = student_repo self._discipline_repo = discipline_repo self._grade_repo = grade_repo if student_repo is None: self._student_repo = StudentRepo(self._generate_students()) if discipline_repo is None: self._discipline_repo = DisciplineRepo( self._generate_disciplines()) if grade_repo is None: self._grade_repo = GradesRepo(self._generate_grades()) self._undo_service = UndoService(self._student_repo, self._discipline_repo, self._grade_repo)
def rem_student(self, student): StudentRepo.rem_student(self, student) self._save_file()
def upd_student(self, sid, name): StudentRepo.upd_student(self, sid, name) self._save_file()
def add_student(self, student): StudentRepo.add_student(self, student) self._save_file()
class Service: def __init__(self, student_repo=None, discipline_repo=None, grade_repo=None): self._student_repo = student_repo self._discipline_repo = discipline_repo self._grade_repo = grade_repo if student_repo is None: self._student_repo = StudentRepo(self._generate_students()) if discipline_repo is None: self._discipline_repo = DisciplineRepo( self._generate_disciplines()) if grade_repo is None: self._grade_repo = GradesRepo(self._generate_grades()) self._undo_service = UndoService(self._student_repo, self._discipline_repo, self._grade_repo) @property def students(self): return self._student_repo.students @property def disciplines(self): return self._discipline_repo.disciplines @property def grades(self): return self._grade_repo.grades @staticmethod def _generate_students(): """ Generates a list with 10 random students :return: list with 10 objects of type Student """ names = Student.list_of_names() students = [] for i in range(min(30, len(names))): name = choice(names) names.remove(name) sid = randrange(1, 1000) while sid in [x.sid for x in students]: sid = randrange(1, 1000) students.append(Student(sid, name)) return students @staticmethod def _generate_disciplines(): """ Generates a list with 10 random disciplines :return: list with 10 objects of type Discipline """ names = Discipline.list_of_names() disciplines = [] for i in range(min(20, len(names))): name = choice(names) names.remove(name) did = randrange(1, 1000) while did in [x.did for x in disciplines]: did = randrange(1, 1000) disciplines.append(Discipline(did, name)) return disciplines def _generate_grades(self): """ Generates a list with 10 random grades :return: list with 10 objects of type Grade """ grades = [] for i in range(100): sid = choice(self._student_repo.students).sid did = choice(self._discipline_repo.disciplines).did grade = randrange(0, 11) grades.append(Grade(sid, did, grade)) return grades def find_student(self, sid): """ Looks for a student with id=sid and returns one if it exists, None otherwise :param sid: int """ return self._student_repo.find_student(sid) def find_discipline(self, did): """ Looks for a discipline with id=did and returns one if it exists, None otherwise :param did: int """ return self._discipline_repo.find_discipline(did) def add_student(self, sid, name): """ Adds a student by calling the student repo :param sid: int :param name: string :return: None """ student = Student(sid, name) if self._student_repo.find_student(sid): raise UniqueError("Student with id already exists") self._undo_service.register_operation( UndoObject(lambda: self._student_repo.rem_student(student), lambda: self._student_repo.add_student(student))) self._student_repo.add_student(student) def add_discipline(self, did, name): """ Adds a discipline by calling the discipline repo :param did: int :param name: string :return: None """ discipline = Discipline(did, name) if self._discipline_repo.find_discipline(did): raise UniqueError("Discipline with id already exists") self._undo_service.register_operation( UndoObject( lambda: self._discipline_repo.rem_discipline(discipline), lambda: self._discipline_repo.add_discipline(discipline))) self._discipline_repo.add_discipline(discipline) def rem_student(self, sid): """ Removes the student with id=sid from the student_repo :param sid: integer :return: None """ student = self._student_repo.find_student(sid) if not student: raise ExistenceError("No student with given id") grades = list(filter(lambda x: x.sid == sid, self._grade_repo.grades)) def undo_function(): self._student_repo.add_student(student) for grade in grades: self._grade_repo.add_grade(grade) def redo_function(): self._student_repo.rem_student(student) for grade in grades: self._grade_repo.rem_grade(grade) self._undo_service.register_operation( UndoObject(undo_function, redo_function)) self._student_repo.rem_student(student) for y in [x for x in self._grade_repo.grades if x.sid == sid]: self._grade_repo.rem_grade(y) def rem_discipline(self, did): """ Removes the discipline with id=did from the discipline repo :param did: :return: None """ discipline = self._discipline_repo.find_discipline(did) if not discipline: raise ExistenceError("No discipline with given id") grades = list(filter(lambda x: x.did == did, self._grade_repo.grades)) def undo_function(): self._discipline_repo.add_discipline(discipline) for grade in grades: self._grade_repo.add_grade(grade) def redo_function(): self._discipline_repo.rem_discipline(discipline) for grade in grades: self._grade_repo.rem_grade(grade) self._undo_service.register_operation( UndoObject(undo_function, redo_function)) self._discipline_repo.rem_discipline(discipline) for y in [x for x in self._grade_repo.grades if x.did == did]: self._grade_repo.rem_grade(y) def upd_student(self, sid, name): """ Sets the name of student from student_repo with id=sid to name :param sid: integer :param name: string :return: None """ student = self._student_repo.find_student(sid) if not student: raise ExistenceError("No student with given id") old_name = student.name self._undo_service.register_operation( UndoObject(lambda: self._student_repo.upd_student(sid, old_name), lambda: self._student_repo.upd_student(sid, name))) self._student_repo.upd_student(sid, name) def upd_discipline(self, did, name): """ Sets the name of discipline from discipline_repo with id=did to name :param did: integer :param name: string :return: None """ discipline = self._discipline_repo.find_discipline(did) if not discipline: raise ExistenceError("No discipline with given id") old_name = discipline.name self._undo_service.register_operation( UndoObject( lambda: self._discipline_repo.upd_discipline(did, old_name), lambda: self._discipline_repo.upd_discipline(did, name))) self._discipline_repo.upd_discipline(did, name) def grade_student(self, sid, did, grade_value): """ Adds a grade to the list from grade_repo :param sid: int :param did: int :param grade_value: int :return: None """ grade = Grade(sid, did, grade_value) if not self._student_repo.find_student(grade.sid): raise ExistenceError("No student with given id") if not self._discipline_repo.find_discipline(grade.did): raise ExistenceError("No discipline with given id") self._undo_service.register_operation( UndoObject(lambda: self._grade_repo.rem_grade(grade), lambda: self._grade_repo.add_grade(grade))) self._grade_repo.add_grade(grade) def lookup_student(self, name): """ Returns a list of all students who match the name with the parameter name, case insensitive :param name: string :return: list """ return [ student for student in self._student_repo.students if re.search(name, student.name, re.IGNORECASE) ] def lookup_discipline(self, name): """ Returns a list of all disciplines who match the name with the parameter name, case insensitive :param name: string :return: list """ return [ discipline for discipline in self._discipline_repo.disciplines if re.search(name, discipline.name, re.IGNORECASE) ] def list_grades_to_string(self): """ :return: list of user readable strings made from each grade in the list of grades """ s = [] for i in self._grade_repo.grades: s.append( "Student {0} with id={1} has grade {2} at discipline {3} with id={4}" .format([ x.name for x in self._student_repo.students if x.sid == i.sid ][0], i.sid, i.grade, [ x.name for x in self._discipline_repo.disciplines if x.did == i.did ][0], i.did)) return s def _grouping_students(self): """ Returns a dictionary with key as student.sid and value as another dictionary with key as discipline.did and value as the average grade at that discipline for that student :return: dict """ d_cnt = {} d_sum = {} for g in self._grade_repo.grades: if g.sid not in d_cnt: d_cnt[g.sid] = {} if g.did not in d_cnt[g.sid]: d_cnt[g.sid][g.did] = 0 if g.sid not in d_sum: d_sum[g.sid] = {} if g.did not in d_sum[g.sid]: d_sum[g.sid][g.did] = 0 d_cnt[g.sid][g.did] += 1 d_sum[g.sid][g.did] += g.grade for key in d_sum: for key2 in d_sum[key]: d_sum[key][key2] /= d_cnt[key][key2] return d_sum def students_failing(self): """ Returns a list of triples(triples are lists with 3 elements), first element is student.sid, second element is discipline.did and third element is the grade of that student at that discipline. Returns only the triples with grade < 5(the failing grade) :return: list """ d = self._grouping_students() v = [] for key in d: for key2 in d[key]: if d[key][key2] < 5: v.append([key, key2, d[key][key2]]) return v def students_failing_to_string(self): """ :return: list of user readable strings for each failing student """ s = [] for x in self.students_failing(): s.append("Student {0} is failing at {1} with grade {2}".format( self.find_student(x[0]).name, self.find_discipline(x[1]).name, x[2])) return s def rank_students(self): """ returns a list of pairs(pairs are lists of 2 elements), first element is student.sid, second element is weighted average grade of that student across all disciplines sorted in descending order of grade :return: list """ d = self._grouping_students() v = [] for key in d: v.append([key, 0]) for key2 in d[key]: v[-1][1] += d[key][key2] v[-1][1] /= len(d[key]) return sort(v, key=lambda x: x[1], reverse=True) def rank_students_to_string(self): """ :return: list of user readable strings for the ranking of students """ s = [] for x in self.rank_students(): s.append("Student {0} has an aggregated average of {1}".format( self.find_student(x[0]).name, x[1])) return s def rank_disciplines(self): """ returns a list of pairs(pairs are lists of 2 elements), first element is discipline.sid, second element is average grade of that discipline across all grades sorted in descending order of grade :return: list """ d = self._grouping_students() d2_sum = {} d2_cnt = {} for sid in d: for did in d[sid]: if did not in d2_sum: d2_sum[did] = 0 d2_sum[did] += d[sid][did] if did not in d2_cnt: d2_cnt[did] = 0 d2_cnt[did] += 1 for did in d2_sum: d2_sum[did] /= d2_cnt[did] v = [] for key, value in d2_sum.items(): v.append([key, value]) return sort(v, key=lambda x: x[1], reverse=True) def rank_disciplines_to_string(self): """ :return: list of user readable strings for the ranking of disciplines """ s = [] for x in self.rank_disciplines(): s.append( "Discipline {0} has average grade of {1} across all students". format(self.find_discipline(x[0]).name, x[1])) return s def undo(self): """ undo function from service """ self._undo_service.undo() def redo(self): """ redo function from service """ self._undo_service.redo()