示例#1
0
class Services:
    def __init__(self):
        self.students = Repository(Repository.TYPE_STUDENTS)
        self.disciplines = Repository(Repository.TYPE_DISCIPLINES)
        self.grades = Repository(Repository.TYPE_GRADES)
        self.tracker = ActionTracker(self)

    def get_students_count(self):
        return self.students.get_size()

    def get_disciplines_count(self):
        return self.disciplines.get_size()

    def get_grades_count(self):
        return self.grades.get_size()

    def has_students(self):
        return self.students.is_not_empty()

    def has_disciplines(self):
        return self.disciplines.is_not_empty()

    def has_grades(self):
        return self.grades.is_not_empty()

    def is_empty(self):
        return self.students.is_empty() and self.disciplines.is_empty(
        ) and self.grades.is_empty()

    def clear(self):
        self.students.clear()
        self.disciplines.clear()
        self.grades.clear()

    def add_all(self, other, track=True):
        self.students.add_all(other.students)
        self.disciplines.add_all(other.disciplines)
        self.grades.add_all(other.grades)
        if track:
            self.tracker.add_action(ActionTracker.ADD_MULTIPLE, other)

    def is_student_id(self, sid):
        for s in self.students:
            if s.id == sid:
                return True
        return False

    def is_discipline_id(self, did):
        for d in self.disciplines:
            if d.id == did:
                return True
        return False

    def add_student(self, sid, name, track=True):
        student = Student(sid, name)
        self.students.add(student)
        if track:
            self.tracker.add_action(ActionTracker.ADD, student,
                                    ActionTracker.STUDENT)

    def add_discipline(self, did, name, track=True):
        discipline = Discipline(did, name)
        self.disciplines.add(discipline)
        if track:
            self.tracker.add_action(ActionTracker.ADD, discipline,
                                    ActionTracker.DISCIPLINE)

    def get_discipline(self, did):
        for d in self.disciplines:
            if d.id == did:
                return d
        raise Exception("Invalid discipline ID, no discipline found with ID " +
                        str(did))

    def get_student(self, sid):
        for s in self.students:
            if s.id == sid:
                return s
        raise Exception("Invalid student ID, no student found with ID " +
                        str(sid))

    def add_grade(self, discipline, student, value, track=True):
        if is_int(discipline):
            discipline = self.get_discipline(discipline)

        if is_int(student):
            student = self.get_student(student)

        grade = Grade(discipline, student, value)
        self.grades.add(grade)
        if track:
            self.tracker.add_action(ActionTracker.ADD, grade,
                                    ActionTracker.GRADE)

    def remove_student(self, sid, track=True):
        deleted = Group()
        student = self.get_student(sid)

        grades_copy = list(self.grades)
        for g in grades_copy:
            if g.student == student:
                deleted.grades.append(g)
                self.grades.remove(g)

        deleted.students.append(student)
        self.students.remove(student)
        if track:
            self.tracker.add_action(ActionTracker.REMOVE_MULTIPLE, deleted)

    def remove_discipline(self, did, track=True):
        deleted = Group()
        discipline = self.get_discipline(did)

        grades_copy = list(self.grades)
        for g in grades_copy:
            if g.discipline == discipline:
                deleted.grades.append(g)
                self.grades.remove(g)

        deleted.disciplines.append(discipline)
        self.disciplines.remove(discipline)
        if track:
            self.tracker.add_action(ActionTracker.REMOVE_MULTIPLE, deleted)

    def update_student(self, sid, name, track=True):
        student = self.get_student(sid)
        if track:
            self.tracker.add_action(ActionTracker.EDIT, copy.copy(student),
                                    ActionTracker.STUDENT)
        student.name = name

    def update_discipline(self, did, name, track=True):
        discipline = self.get_discipline(did)
        if track:
            self.tracker.add_action(ActionTracker.EDIT, copy.copy(discipline),
                                    ActionTracker.DISCIPLINE)
        discipline.name = name

    def search(self, keyword):
        search_group = Group()
        keyword = keyword.upper()

        for s in self.students:
            if keyword in str(s.id).upper() or keyword in s.name.upper():
                search_group.students.append(s)
        for d in self.disciplines:
            if keyword in str(d.id).upper() or keyword in d.name.upper():
                search_group.disciplines.append(d)

        return search_group

    def get_failing_students(self):
        students_with_grades = []

        for s in self.students:
            for d in self.disciplines:
                count = 0
                average = 0

                for g in self.grades:
                    if g.student == s and g.discipline == d:
                        count += 1
                        average += g.value

                if count == 0:
                    continue

                average /= count

                if average < 5:
                    students_with_grades.append(
                        Average(average, s.name, d.name))

        return students_with_grades

    def get_best_students(self):
        students_with_grades = []

        for s in self.students:
            total_count = 0
            total_average = 0

            for d in self.disciplines:
                count = 0
                average = 0

                for g in self.grades:
                    if g.student == s and g.discipline == d:
                        count += 1
                        average += g.value

                if count == 0:
                    continue

                total_count += 1
                total_average += average / count

            if total_count == 0:
                continue

            total_average /= total_count
            students_with_grades.append(
                Average(total_average, student_name=s.name))

        return students_with_grades

    def get_disciplines_with_grades(self):
        disciplines_with_grades = []

        for d in self.disciplines:
            count = 0
            average = 0

            for g in self.grades:
                if g.discipline == d:
                    count += 1
                    average += g.value

            if count == 0:
                continue

            average /= count
            disciplines_with_grades.append(
                Average(average, discipline_name=d.name))

        return disciplines_with_grades

    def undo(self):
        self.tracker.undo()

    def redo(self):
        self.tracker.redo()
示例#2
0
class Services:
    def __init__(self):
        self.repository = Repository()

    def preload_list(self):
        """
        Adds to the repository a list of predefined values that are randomised

        Input: -
        Output: -
        """
        randomiser = Randomiser()
        repository_to_add = Repository()

        for i in range(10):
            random_name = randomiser.get_random_first_name(
            ) + " " + randomiser.get_random_last_name()

            repository_to_add.add_student(i, random_name)
            repository_to_add.add_discipline(
                i, randomiser.get_random_discipline_name())

        for i in range(10):
            repository_to_add.add_grade(
                randomiser.get_random(repository_to_add.disciplines),
                randomiser.get_random(repository_to_add.students),
                randomiser.get_random_grade())

        self.repository.add_all(repository_to_add)

    def add(self, params):
        """
        Add a student or discipline to the repository

        Input: list - list of params (type, id, name)
        Output: -
        """
        validate_param_length(params, 3)

        atype = params[0]
        aid = params[1]
        name = params[2]

        validate_type(atype)
        if atype == STUDENT:
            validate_new_student_id(self.repository, aid)
        if atype == DISCIPLINE:
            validate_new_discipline_id(self.repository, aid)
        validate_name(name)

        aid = int(aid)
        if atype == STUDENT:
            self.repository.add_student(aid, name)
        if atype == DISCIPLINE:
            self.repository.add_discipline(aid, name)

    def remove(self, params):
        """
        Remove a student or discipline from the repository

        Input: list - list of params (type, id)
        Output: -
        """
        validate_param_length(params, 2)

        atype = params[0]
        aid = params[1]

        validate_type(atype)
        if atype == STUDENT:
            validate_existing_student_id(self.repository, aid)
        if atype == DISCIPLINE:
            validate_existing_discipline_id(self.repository, aid)

        aid = int(aid)
        if atype == STUDENT:
            self.repository.remove_student(aid)
        if atype == DISCIPLINE:
            self.repository.remove_discipline(aid)

    def update(self, params):
        """
        Update a student or discipline from the repository

        Input: list - list of params (type, id, new_name)
        Output: -
        """
        validate_param_length(params, 3)

        atype = params[0]
        aid = params[1]
        name = params[2]

        validate_type(atype)
        if atype == STUDENT:
            validate_existing_student_id(self.repository, aid)
        if atype == DISCIPLINE:
            validate_existing_discipline_id(self.repository, aid)
        validate_name(name)

        aid = int(aid)
        if atype == STUDENT:
            self.repository.update_student(aid, name)
        if atype == DISCIPLINE:
            self.repository.update_discipline(aid, name)

    def build_list(self, repository, header="All students and diciplines"):
        """
        Parses a repository's data into a string to be printed

        Input: 
            Repository - repository to parse
            string - header to show at the beginning of the generated string
        Output: string - the parsed repository
        """
        if repository.is_empty():
            raise NoDataError("No data to show")

        data_string = "\n"
        data_string += header

        if repository.has_students() and repository.has_disciplines():
            data_string += "\n" + generator.generate_chars(
                '-', 121) + "\n|" + generator.generate_chars(
                    ' ', 4) + "Students" + generator.generate_chars(
                        ' ', 47) + "|" + generator.generate_chars(
                            ' ', 4) + "Disciplines" + generator.generate_chars(
                                ' ', 44) + "|\n" + generator.generate_chars(
                                    '-', 121)

            students_length = len(repository.students)
            disciplines_length = len(repository.disciplines)
            max_length = max(students_length, disciplines_length)

            for i in range(max_length):
                if i < students_length:
                    student_string = str(repository.students[i])
                    data_string += "\n| " + student_string + generator.generate_chars(
                        ' ', 57 - len(student_string)) + " | "
                else:
                    data_string += "\n|" + generator.generate_chars(' ',
                                                                    59) + "| "
                if i < disciplines_length:
                    discipline_string = str(repository.disciplines[i])
                    data_string += discipline_string + generator.generate_chars(
                        ' ', 57 - len(discipline_string)) + " |"
                else:
                    data_string += generator.generate_chars(' ', 58) + "|"

            data_string += "\n" + generator.generate_chars('-', 121)
            return data_string

        if repository.has_students():
            data_string += "\n" + generator.generate_chars(
                '-', 60) + "\nStudents\n" + generator.generate_chars('-', 60)

            for student in repository.students:
                data_string += "\n" + str(student)

            return data_string

        if repository.has_disciplines():
            data_string += "\n" + generator.generate_chars(
                '-', 60) + "\nDisciplines\n" + generator.generate_chars(
                    '-', 60)

            for discipline in repository.disciplines:
                data_string += "\n" + str(discipline)

            return data_string

    def list_all(self):
        """
        Builds are returns a list as string representing the repository to be printed

        Input: -
        Output: string - string representing the repository
        """
        return self.build_list(self.repository)

    def grade(self, params):
        """
        Gives a grade to a student at a given discipline

        Input: params - list of params (student_id, discipline_id, grade)
        Output: -
        """
        validate_param_length(params, 3)

        sid = params[0]
        did = params[1]
        grade = params[2]

        validate_existing_student_id(self.repository, sid)
        validate_existing_discipline_id(self.repository, did)
        validate_grade(grade)

        self.repository.add_grade(int(did), int(sid), float(grade))

    def search(self, params):
        """
        Searches by a keyword and returns a string with the results

        Input: params - list of params (keyword)
        Output: string - results of search
        """
        validate_param_length(params, 1)

        keyword = params[0]

        validate_keyword(keyword)

        repo_with_search = self.repository.search(keyword)
        return self.build_list(repo_with_search,
                               "Results for the keyword '" + keyword + "'")

    def see_failing_students(self):
        """
        Returns a string representing the failing students

        Input: -
        Output: string - all failing students
        """
        faillings = self.repository.get_failing_students()

        if len(faillings) < 1:
            raise NoDataError("No students failing at one or more disciplines")

        students_to_show = "\nStudents failing:"
        count = 1
        for f in faillings:
            students_to_show += "\n" + str(
                count
            ) + ". " + f.student_name + " at " + f.discipline_name + " with the average of " + f.get_formated_average(
            )
            count += 1
        return students_to_show

    def see_best_students(self):
        """
        Returns a string representing all students ordered by their average grades

        Input: -
        Output: string - all students ordered by their average grades
        """
        best_students = self.repository.get_best_students()

        if len(best_students) < 1:
            raise NoDataError("No students with grades to show")

        best_students = sorted(best_students,
                               key=lambda b: b.value,
                               reverse=True)

        students_to_show = "\nBest students in descending order of average grades:"
        count = 1
        for b in best_students:
            students_to_show += "\n" + str(
                count
            ) + ". " + b.student_name + " with the average of " + b.get_formated_average(
            )
            count += 1
        return students_to_show

    def see_grades(self):
        """
        Returns a string representing all disciplines ordered by their average grades

        Input: -
        Output: string - all disciplines ordered by their average grades
        """
        disciplines_with_grades = self.repository.get_disciplines_with_grades()

        if len(disciplines_with_grades) < 1:
            raise NoDataError("No disciplines with grades to show")

        disciplines_with_grades = sorted(disciplines_with_grades,
                                         key=lambda d: d.value,
                                         reverse=True)

        disciplines_to_show = "\nDisciplines with grades in descending order of average grades:"
        count = 1
        for d in disciplines_with_grades:
            disciplines_to_show += "\n" + str(
                count
            ) + ". " + d.discipline_name + " with the average of " + d.get_formated_average(
            )
            count += 1
        return disciplines_to_show

    def undo(self):
        """
        Undos the last operation that modified the repository

        Input: -
        Output: -
        """
        self.repository.undo()

    def redo(self):
        """
        Redos the last operation that modified the repository

        Input: -
        Output: -
        """
        self.repository.redo()