#PLEASE DO NOT EDIT THIS CODE
#This code was generated using the UMPLE 1.38.0.8942.247e17422 modeling language!


class Student:
    def __init__(self, aNumber):
        self._number = aNumber
        self._mentors = []

    def setNumber(self, aNumber):
        self._number = aNumber
        return True

    def getNumber(self):
        return self._number

    def getMentor(self, index):
        return self._mentors[index]

    def getMentors(self):
        return tuple(self._mentors)

    def numberOfMentors(self):
        return len(self._mentors)

    def hasMentors(self):
        return len(self._mentors) > 0

    def indexOfMentor(self, aMentor):
        return next((i for i, x in enumerate(self._mentors) if x is aMentor), -1)

    @staticmethod
    def minimumNumberOfMentors():
        return 0

    def addMentor(self, aMentor):
        if any(x is aMentor for x in self._mentors):
            return False
        self._mentors.append(aMentor)
        if aMentor.indexOfStudent(self) == -1 and not aMentor.addStudent(self):
            del self._mentors[next((i for i, x in enumerate(self._mentors) if x is aMentor), -1)]
            return False
        return True

    def removeMentor(self, aMentor):
        oldIndex = next((i for i, x in enumerate(self._mentors) if x is aMentor), -1)
        if oldIndex == -1:
            return False
        del self._mentors[oldIndex]
        if aMentor.indexOfStudent(self) != -1 and not aMentor.removeStudent(self):
            self._mentors.insert(oldIndex, aMentor)
            return False
        return True

    def addMentorAt(self, aMentor, index):
        if not self.addMentor(aMentor):
            return False
        if index < 0:
            index = 0
        if index > self.numberOfMentors():
            index = self.numberOfMentors() - 1
        del self._mentors[next((i for i, x in enumerate(self._mentors) if x is aMentor), -1)]
        self._mentors.insert(index, aMentor)
        return True

    def addOrMoveMentorAt(self, aMentor, index):
        if not any(x is aMentor for x in self._mentors):
            return self.addMentorAt(aMentor, index)
        if index < 0:
            index = 0
        if index > self.numberOfMentors():
            index = self.numberOfMentors() - 1
        del self._mentors[next((i for i, x in enumerate(self._mentors) if x is aMentor), -1)]
        self._mentors.insert(index, aMentor)
        return True

    def delete(self):
        from example.Mentor import Mentor
        copyOfMentors = tuple(self._mentors)
        self._mentors.clear()
        for aMentor in copyOfMentors:
            if aMentor.numberOfStudents() <= Mentor.minimumNumberOfStudents():
                aMentor.delete()
            else:
                aMentor.removeStudent(self)

    def __str__(self):
        return (super().__str__() + "["
                + "number:" + str(self.getNumber())
                + "]")

#PLEASE DO NOT EDIT THIS CODE
#This code was generated using the UMPLE 1.38.0.8942.247e17422 modeling language!


class Mentor:
    def __init__(self, aName, *allStudents):
        self._name = aName
        self._students = []
        if not self.setStudents(*allStudents):
            raise RuntimeError("Unable to create Mentor, must have 2 students. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html")

    def setName(self, aName):
        self._name = aName
        return True

    def getName(self):
        return self._name

    def getStudent(self, index):
        return self._students[index]

    def getStudents(self):
        return tuple(self._students)

    def numberOfStudents(self):
        return len(self._students)

    def hasStudents(self):
        return len(self._students) > 0

    def indexOfStudent(self, aStudent):
        return next((i for i, x in enumerate(self._students) if x is aStudent), -1)

    def isNumberOfStudentsValid(self):
        return self.numberOfStudents() >= __class__.minimumNumberOfStudents() and self.numberOfStudents() <= __class__.maximumNumberOfStudents()

    @staticmethod
    def requiredNumberOfStudents():
        return 2

    @staticmethod
    def minimumNumberOfStudents():
        return 2

    @staticmethod
    def maximumNumberOfStudents():
        return 2

    def addStudent(self, aStudent):
        if any(x is aStudent for x in self._students):
            return False
        if self.numberOfStudents() >= __class__.maximumNumberOfStudents():
            return False
        self._students.append(aStudent)
        if aStudent.indexOfMentor(self) == -1 and not aStudent.addMentor(self):
            del self._students[next((i for i, x in enumerate(self._students) if x is aStudent), -1)]
            return False
        return True

    def removeStudent(self, aStudent):
        oldIndex = next((i for i, x in enumerate(self._students) if x is aStudent), -1)
        if oldIndex == -1:
            return False
        if self.numberOfStudents() <= __class__.minimumNumberOfStudents():
            return False
        del self._students[oldIndex]
        if aStudent.indexOfMentor(self) != -1 and not aStudent.removeMentor(self):
            self._students.insert(oldIndex, aStudent)
            return False
        return True

    def setStudents(self, *newStudents):
        if len({id(x) for x in newStudents}) != len(newStudents) or len(newStudents) < __class__.minimumNumberOfStudents() or len(newStudents) > __class__.maximumNumberOfStudents():
            return False
        oldStudents = {id(x): x for x in self._students}
        self._students.clear()
        for aNewStudent in newStudents:
            self._students.append(aNewStudent)
            if id(aNewStudent) in oldStudents:
                del oldStudents[id(aNewStudent)]
            else:
                aNewStudent.addMentor(self)
        for anOldStudent in oldStudents.values():
            anOldStudent.removeMentor(self)
        return True

    def delete(self):
        copyOfStudents = tuple(self._students)
        self._students.clear()
        for aStudent in copyOfStudents:
            aStudent.removeMentor(self)

    def __str__(self):
        return (super().__str__() + "["
                + "name:" + str(self.getName())
                + "]")