class Student():
    def __init__(self):
        self._mentors = None
        self._mentors = []

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

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

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

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

    def indexOfMentor(self, aMentor):
        index = (-1 if not aMentor in self._mentors else self._mentors.index(aMentor))
        return index

    @staticmethod
    def minimumNumberOfMentors():
        return 0

    def addMentor(self, aMentor):
        wasAdded = False
        if (aMentor) in self._mentors :
            return False
        self._mentors.append(aMentor)
        if aMentor.indexOfStudent(self) != -1 :
            wasAdded = True
        else :
            wasAdded = aMentor.addStudent(self)
            if not wasAdded :
                self._mentors.remove(aMentor)
        return wasAdded

    def removeMentor(self, aMentor):
        wasRemoved = False
        if not (aMentor) in self._mentors :
            return wasRemoved
        oldIndex = (-1 if not aMentor in self._mentors else self._mentors.index(aMentor))
        self._mentors.remove(oldIndex)
        if aMentor.indexOfStudent(self) == -1 :
            wasRemoved = True
        else :
            wasRemoved = aMentor.removeStudent(self)
            if not wasRemoved :
                self._mentors.insert(oldIndex, aMentor)
        return wasRemoved

    def addMentorAt(self, aMentor, index):
        wasAdded = False
        if self.addMentor(aMentor) :
            if index < 0 :
                index = 0
            if index > self.numberOfMentors() :
                index = self.numberOfMentors() - 1
            self._mentors.remove(aMentor)
            self._mentors.insert(index, aMentor)
            wasAdded = True
        return wasAdded

    def addOrMoveMentorAt(self, aMentor, index):
        wasAdded = False
        if (aMentor) in self._mentors :
            if index < 0 :
                index = 0
            if index > self.numberOfMentors() :
                index = self.numberOfMentors() - 1
            self._mentors.remove(aMentor)
            self._mentors.insert(index, aMentor)
            wasAdded = True
        else :
            wasAdded = self.addMentorAt(aMentor, index)
        return wasAdded

    def delete(self):
        copyOfMentors = self._mentors.copy()
        self._mentors.clear()
        for aMentor in copyOfMentors:
            aMentor.removeStudent(self)


class Student():
    def __init__(self):
        self._mentors = None
        self._mentors = []

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

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

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

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

    def indexOfMentor(self, aMentor):
        index = (-1 if not aMentor in self._mentors else self._mentors.index(aMentor))
        return index

    @staticmethod
    def minimumNumberOfMentors():
        return 0

    def addMentor(self, aMentor):
        wasAdded = False
        if (aMentor) in self._mentors :
            return False
        self._mentors.append(aMentor)
        if aMentor.indexOfStudent(self) != -1 :
            wasAdded = True
        else :
            wasAdded = aMentor.addStudent(self)
            if not wasAdded :
                self._mentors.remove(aMentor)
        return wasAdded

    def removeMentor(self, aMentor):
        wasRemoved = False
        if not (aMentor) in self._mentors :
            return wasRemoved
        oldIndex = (-1 if not aMentor in self._mentors else self._mentors.index(aMentor))
        self._mentors.remove(oldIndex)
        if aMentor.indexOfStudent(self) == -1 :
            wasRemoved = True
        else :
            wasRemoved = aMentor.removeStudent(self)
            if not wasRemoved :
                self._mentors.insert(oldIndex, aMentor)
        return wasRemoved

    def addMentorAt(self, aMentor, index):
        wasAdded = False
        if self.addMentor(aMentor) :
            if index < 0 :
                index = 0
            if index > self.numberOfMentors() :
                index = self.numberOfMentors() - 1
            self._mentors.remove(aMentor)
            self._mentors.insert(index, aMentor)
            wasAdded = True
        return wasAdded

    def addOrMoveMentorAt(self, aMentor, index):
        wasAdded = False
        if (aMentor) in self._mentors :
            if index < 0 :
                index = 0
            if index > self.numberOfMentors() :
                index = self.numberOfMentors() - 1
            self._mentors.remove(aMentor)
            self._mentors.insert(index, aMentor)
            wasAdded = True
        else :
            wasAdded = self.addMentorAt(aMentor, index)
        return wasAdded

    def delete(self):
        copyOfMentors = self._mentors.copy()
        self._mentors.clear()
        for aMentor in copyOfMentors:
            aMentor.removeStudent(self)


class Student():
    def __init__(self, aIntId, aDoubleId, aBooleanId, aStringId):
        self._canSetStringListIds = None
        self._canSetStringId = None
        self._canSetBooleanId = None
        self._canSetDoubleId = None
        self._canSetIntId = None
        self._cachedHashCode = None
        self._stringListIds = None
        self._stringId = None
        self._booleanId = None
        self._doubleId = None
        self._intId = None
        self._cachedHashCode = -1
        self._canSetIntId = True
        self._canSetDoubleId = True
        self._canSetBooleanId = True
        self._canSetStringId = True
        self._canSetStringListIds = True
        self._intId = aIntId
        self._doubleId = aDoubleId
        self._booleanId = aBooleanId
        self._stringId = aStringId
        self._stringListIds = []

    def setIntId(self, aIntId):
        wasSet = False
        if not self._canSetIntId :
            return False
        self._intId = aIntId
        wasSet = True
        return wasSet

    def setDoubleId(self, aDoubleId):
        wasSet = False
        if not self._canSetDoubleId :
            return False
        self._doubleId = aDoubleId
        wasSet = True
        return wasSet

    def setBooleanId(self, aBooleanId):
        wasSet = False
        if not self._canSetBooleanId :
            return False
        self._booleanId = aBooleanId
        wasSet = True
        return wasSet

    def setStringId(self, aStringId):
        wasSet = False
        if not self._canSetStringId :
            return False
        self._stringId = aStringId
        wasSet = True
        return wasSet

    def addStringListId(self, aStringListId):
        wasAdded = False
        if not self._canSetStringListIds :
            return False
        wasAdded = self._stringListIds.append(aStringListId)
        return wasAdded

    def removeStringListId(self, aStringListId):
        wasRemoved = False
        if not self._canSetStringListIds :
            return False
        wasRemoved = self._stringListIds.remove(aStringListId)
        return wasRemoved

    def getIntId(self):
        return self._intId

    def getDoubleId(self):
        return self._doubleId

    def getBooleanId(self):
        return self._booleanId

    def getStringId(self):
        return self._stringId

    def getStringListId(self, index):
        aStringListId = self._stringListIds[index]
        return aStringListId

    def getStringListIds(self):
        newStringListIds = self._stringListIds.copy()
        return newStringListIds

    def numberOfStringListIds(self):
        number = len(self._stringListIds)
        return number

    def hasStringListIds(self):
        has = len(self._stringListIds) > 0
        return has

    def indexOfStringListId(self, aStringListId):
        index = (-1 if not aStringListId in self._stringListIds else self._stringListIds.index(aStringListId))
        return index

    def isBooleanId(self):
        return self._booleanId

    def equals(self, obj):
        if obj is None :
            return False
        if not type(self) is type(obj) :
            return False
        compareTo = obj
        if self.getIntId() != compareTo.getIntId() :
            return False
        if self.getDoubleId() != compareTo.getDoubleId() :
            return False
        if self.getBooleanId() != compareTo.getBooleanId() :
            return False
        if self.getStringId() is None and not (compareTo.getStringId() is None) :
            return False
        elif not (self.getStringId() is None) and not self.getStringId() == compareTo.getStringId() :
            return False
        if self.getStringListIds().length != compareTo.getStringListIds().length :
            return False
        i = 0
        while i < self.getStringListIds().length :
            me = self.getStringListIds()
            them = compareTo.getStringListIds()[i]
            if me is None and not (them is None) :
                return False
            elif not (me is None) and not me == them :
                return False
            i += 1

        return True

    def __hash__(self):
        if self._cachedHashCode != -1 :
            return self._cachedHashCode
        self._cachedHashCode = 17
        self._cachedHashCode = self._cachedHashCode * 23 + self.getIntId()
        self._cachedHashCode = self._cachedHashCode * 23 + (float(self.getDoubleId())).__hash__()
        self._cachedHashCode = self._cachedHashCode * 23 + ((1) if self.getBooleanId() else 0)
        if not (self.getStringId() is None) :
            self._cachedHashCode = self._cachedHashCode * 23 + self.getStringId().__hash__()
        else :
            self._cachedHashCode = self._cachedHashCode * 23
        if not (self.getStringListIds() is None) :
            self._cachedHashCode = self._cachedHashCode * 23 + self.getStringListIds().__hash__()
        else :
            self._cachedHashCode = self._cachedHashCode * 23
        self._canSetIntId = False
        self._canSetDoubleId = False
        self._canSetBooleanId = False
        self._canSetStringId = False
        self._canSetStringListIds = False
        return self._cachedHashCode

    def delete(self):
        pass

    def __str__(self):
        return str(super().__str__()) + "[" + "stringId" + ":" + str(self.getStringId()) + "," + "booleanId" + ":" + str(self.getBooleanId()) + "," + "doubleId" + ":" + str(self.getDoubleId()) + "," + "intId" + ":" + str(self.getIntId()) + "]"


class Student():
    def __init__(self, aDoubleId, aBooleanId, aStringId):
        self._canSetIntId = None
        self._cachedHashCode = None
        self._stringId = None
        self._booleanId = None
        self._doubleId = None
        self._intId = None
        self._cachedHashCode = -1
        self._canSetIntId = True
        self._doubleId = aDoubleId
        self._booleanId = aBooleanId
        self._stringId = aStringId

    def setIntId(self, aIntId):
        wasSet = False
        if not self._canSetIntId :
            return False
        self._canSetIntId = False
        self._intId = aIntId
        wasSet = True
        return wasSet

    def getIntId(self):
        return self._intId

    def getDoubleId(self):
        return self._doubleId

    def getBooleanId(self):
        return self._booleanId

    def getStringId(self):
        return self._stringId

    def isBooleanId(self):
        return self._booleanId

    def equals(self, obj):
        if obj is None :
            return False
        if not type(self) is type(obj) :
            return False
        compareTo = obj
        if self.getIntId() != compareTo.getIntId() :
            return False
        if self.getDoubleId() != compareTo.getDoubleId() :
            return False
        if self.getBooleanId() != compareTo.getBooleanId() :
            return False
        if self.getStringId() is None and not (compareTo.getStringId() is None) :
            return False
        elif not (self.getStringId() is None) and not self.getStringId() == compareTo.getStringId() :
            return False
        return True

    def __hash__(self):
        if self._cachedHashCode != -1 :
            return self._cachedHashCode
        self._cachedHashCode = 17
        self._cachedHashCode = self._cachedHashCode * 23 + self.getIntId()
        self._cachedHashCode = self._cachedHashCode * 23 + (float(self.getDoubleId())).__hash__()
        self._cachedHashCode = self._cachedHashCode * 23 + ((1) if self.getBooleanId() else 0)
        if not (self.getStringId() is None) :
            self._cachedHashCode = self._cachedHashCode * 23 + self.getStringId().__hash__()
        else :
            self._cachedHashCode = self._cachedHashCode * 23
        self._canSetIntId = False
        return self._cachedHashCode

    def delete(self):
        pass

    def __str__(self):
        return str(super().__str__()) + "[" + "stringId" + ":" + str(self.getStringId()) + "," + "booleanId" + ":" + str(self.getBooleanId()) + "," + "doubleId" + ":" + str(self.getDoubleId()) + "," + "intId" + ":" + str(self.getIntId()) + "]"


class Mentor():
    def __init__(self):
        self._canSetSecondaries = None
        self._canSetMain = None
        self._cachedHashCode = None
        self._secondaries = None
        self._main = None
        self._cachedHashCode = -1
        self._canSetMain = True
        self._canSetSecondaries = True
        self._secondaries = []

    def getMain(self):
        return self._main

    def hasMain(self):
        has = not (self._main is None)
        return has

    def getSecondary(self, index):
        aSecondary = self._secondaries[index]
        return aSecondary

    def getSecondaries(self):
        newSecondaries = tuple(self._secondaries)
        return newSecondaries

    def numberOfSecondaries(self):
        number = len(self._secondaries)
        return number

    def hasSecondaries(self):
        has = len(self._secondaries) > 0
        return has

    def indexOfSecondary(self, aSecondary):
        index = (-1 if not aSecondary in self._secondaries else self._secondaries.index(aSecondary))
        return index

    def setMain(self, aNewMain):
        wasSet = False
        if not self._canSetMain :
            return False
        if aNewMain is None :
            existingMain = self._main
            self._main = None
            if not (existingMain is None) and not (existingMain.getMentorMain() is None) :
                existingMain.setMentorMain(None)
            wasSet = True
            return wasSet
        currentMain = self.getMain()
        if not (currentMain is None) and not currentMain == aNewMain :
            currentMain.setMentorMain(None)
        self._main = aNewMain
        existingMentorMain = aNewMain.getMentorMain()
        if not self == existingMentorMain :
            aNewMain.setMentorMain(self)
        wasSet = True
        return wasSet

    @staticmethod
    def minimumNumberOfSecondaries():
        return 0

    def addSecondary(self, aSecondary):
        wasAdded = False
        if not self._canSetSecondaries :
            return False
        if (aSecondary) in self._secondaries :
            return False
        existingMentorSecondary = aSecondary.getMentorSecondary()
        if existingMentorSecondary is None :
            aSecondary.setMentorSecondary(self)
        elif not self == existingMentorSecondary :
            existingMentorSecondary.removeSecondary(aSecondary)
            self.addSecondary(aSecondary)
        else :
            self._secondaries.append(aSecondary)
        wasAdded = True
        return wasAdded

    def removeSecondary(self, aSecondary):
        wasRemoved = False
        if not self._canSetSecondaries :
            return False
        if (aSecondary) in self._secondaries :
            self._secondaries.remove(aSecondary)
            aSecondary.setMentorSecondary(None)
            wasRemoved = True
        return wasRemoved

    def addSecondaryAt(self, aSecondary, index):
        wasAdded = False
        if self.addSecondary(aSecondary) :
            if index < 0 :
                index = 0
            if index > self.numberOfSecondaries() :
                index = self.numberOfSecondaries() - 1
            self._secondaries.remove(aSecondary)
            self._secondaries.insert(index, aSecondary)
            wasAdded = True
        return wasAdded

    def addOrMoveSecondaryAt(self, aSecondary, index):
        wasAdded = False
        if (aSecondary) in self._secondaries :
            if index < 0 :
                index = 0
            if index > self.numberOfSecondaries() :
                index = self.numberOfSecondaries() - 1
            self._secondaries.remove(aSecondary)
            self._secondaries.insert(index, aSecondary)
            wasAdded = True
        else :
            wasAdded = self.addSecondaryAt(aSecondary, index)
        return wasAdded

    def equals(self, obj):
        if obj is None :
            return False
        if not type(self) is type(obj) :
            return False
        compareTo = obj
        if self.getMain() is None and not (compareTo.getMain() is None) :
            return False
        elif not (self.getMain() is None) and not self.getMain() == compareTo.getMain() :
            return False
        if self.getSecondaries().size() != compareTo.getSecondaries().size() :
            return False
        i = 0
        while i < self.getSecondaries().size() :
            me = self.getSecondaries().get(i)
            them = compareTo.getSecondaries().get(i)
            if me is None and not (them is None) :
                return False
            elif not (me is None) and not me == them :
                return False
            i += 1

        return True

    def __hash__(self):
        if self._cachedHashCode != -1 :
            return self._cachedHashCode
        self._cachedHashCode = 17
        if not (self.getMain() is None) :
            self._cachedHashCode = self._cachedHashCode * 23 + self.getMain().__hash__()
        else :
            self._cachedHashCode = self._cachedHashCode * 23
        if not (self.getSecondaries() is None) :
            self._cachedHashCode = self._cachedHashCode * 23 + self.getSecondaries().__hash__()
        else :
            self._cachedHashCode = self._cachedHashCode * 23
        self._canSetMain = False
        self._canSetSecondaries = False
        return self._cachedHashCode

    def delete(self):
        if not (self._main is None) :
            self._main.setMentorMain(None)

        while not self._secondaries.isEmpty() :
            self._secondaries[0].setMentorSecondary(None)