from django.test import TestCase
from scheduler.Scheduler import Scheduler
from common.models import *
from scheduler.simulator import Simulator

SIMULATION_FILE = 'file:./scheduler/sequences_cador.html'


class SchedulerTest(TestCase):

    # (EP) Create a fixture in memory with 1 scheduler, 3 requests belonging to 3 different users
    def setUp(self):
        '''
            Creates the scheduler
            Creates 3 users (and associated needs)
            Creates 3 requests

            Creates associated needs : scientific program, country, user_level
        '''

        self.scheduler = Scheduler()

        self.scheduler.max_overhead = 1

        scipro = ScientificProgram.objects.create()
        country = Country.objects.create()
        user_level = UserLevel.objects.create()

        self.usr1 = PyrosUser.objects.create(username="toto", country=country, user_level=user_level, quota=100)
        self.usr2 = PyrosUser.objects.create(username="titi", country=country, user_level=user_level, quota=100)
        self.usr3 = PyrosUser.objects.create(username="tata", country=country, user_level=user_level, quota=100)

        self.req1 = Request.objects.create(pyros_user=self.usr1, scientific_program=scipro)
        self.req2 = Request.objects.create(pyros_user=self.usr2, scientific_program=scipro)
        self.req3 = Request.objects.create(pyros_user=self.usr3, scientific_program=scipro)

    def test_basic_3_seq(self):
        '''
            goal : test if 3 distinct sequences are put into the planning
            conditions : the sequence have the same priority, and have no jd overlap
        '''

        print("\n===== TEST_BASIC_3_SEQ =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 10

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=2, priority=1, t_prefered=-1, duration=1)
        seq2 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=4, jd2=6, priority=1, t_prefered=-1, duration=1)
        seq3 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=7, jd2=9, priority=1, t_prefered=-1, duration=1)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        self.assertEqual(nbPlanned, 3)

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''

        self.assertEqual(shs1.tsp, 1)
        self.assertEqual(shs1.tep, 2)
        self.assertEqual(shs1.deltaTL, 0)
        self.assertEqual(shs1.deltaTR, 0)

        self.assertEqual(shs2.tsp, 4)
        self.assertEqual(shs2.tep, 5)
        self.assertEqual(shs2.deltaTL, 0)
        self.assertEqual(shs2.deltaTR, 1)

        self.assertEqual(shs3.tsp, 7)
        self.assertEqual(shs3.tep, 8)
        self.assertEqual(shs3.deltaTL, 0)
        self.assertEqual(shs3.deltaTR, 1)

    def test_3_seq_with_quotas(self):
        '''
            goal : test if the quotas are decreased
            conditions : the sequences have the same priority, and various durations
        '''

        print("\n===== TEST_3_SEQ_WITH_QUOTAS =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 100

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=1, jd2=30, priority=1, t_prefered=-1, duration=3)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=1, jd2=30, priority=1, t_prefered=-1, duration=10)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=1, jd2=30, priority=1, t_prefered=-1, duration=5)

        seq1.request.pyros_user.quota = 100
        seq1.request.pyros_user.save()
        seq2.request.pyros_user.quota = 100
        seq2.request.pyros_user.save()
        seq3.request.pyros_user.quota = 100
        seq3.request.pyros_user.save()

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        seq1 = Sequence.objects.get(name="seq1")
        seq2 = Sequence.objects.get(name="seq2")
        seq3 = Sequence.objects.get(name="seq3")

        ''' checks sequence owners' quotas '''

        self.assertEqual(nbPlanned, 3)

        self.assertEqual(seq1.request.pyros_user.quota, 100 - 3)
        self.assertEqual(seq2.request.pyros_user.quota, 100 - 10)
        self.assertEqual(seq3.request.pyros_user.quota, 100 - 5)

    def test_4_seq_insufficient_quotas(self):
        '''
            goal : test if an insufficient quota blocks sequence programmation
            conditions : the sequences have the same priority, a user has 2 sequence, the others have 1 Sequence
        '''

        print("\n===== TEST_4_SEQ_INSUFFICIENT_QUOTAS =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 100

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=1, jd2=200, priority=1, t_prefered=-1, duration=3)
        seq2 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=1, jd2=200, priority=1, t_prefered=-1, duration=10)
        seq3 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=1, jd2=200, priority=1, t_prefered=-1, duration=10)
        seq4 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq4", jd1=1, jd2=200, priority=1, t_prefered=-1, duration=15)

        seq1.request.pyros_user.quota = 11
        seq1.request.pyros_user.save()
        seq3.request.pyros_user.quota = 10
        seq3.request.pyros_user.save()
        seq4.request.pyros_user.quota = 14
        seq4.request.pyros_user.save()

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        seq1 = Sequence.objects.get(name="seq1")
        seq2 = Sequence.objects.get(name="seq2")
        seq3 = Sequence.objects.get(name="seq3")
        seq4 = Sequence.objects.get(name="seq4")

        ''' checks sequence owners' quotas '''

        self.assertEqual(nbPlanned, 2)

        self.assertEqual(seq1.request.pyros_user.quota, 11 - 3 - 0)
        self.assertEqual(seq3.request.pyros_user.quota, 10 - 10)
        self.assertEqual(seq4.request.pyros_user.quota, 14 - 0)

    def test_3_seq_priority(self):
        '''
            goal : test if the priority is taken into account when there isn't enough room
            conditions : sequences have different priorities, are visible the whole night and can't be all put
        '''

        print("\n===== TEST_3_SEQ_PRIORITY =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 20

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=1, jd2=200, priority=10, t_prefered=-1, duration=10)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=1, jd2=200, priority=9, t_prefered=-1, duration=11)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=1, jd2=200, priority=11, t_prefered=-1, duration=10)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)

        ''' checks which sequence is planned '''

        self.assertEqual(nbPlanned, 1)

        self.assertEqual(shs2.status, Sequence.PLANNED)

    def test_3_seq_priority_overlap(self):
        '''
            goal : test if the sequences are arranged according to the priorities
            conditions : sequences have different priorities, are visible the whole night and can be all put (enough room)
        '''

        print("\n===== TEST_3_SEQ_PRIORITY_OVERLAP =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 200

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=1, jd2=200, priority=10, t_prefered=-1, duration=10)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=1, jd2=200, priority=9, t_prefered=-1, duration=11)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=1, jd2=200, priority=11, t_prefered=-1, duration=12)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''

        self.assertEqual(nbPlanned, 3)

        self.assertEqual(shs2.tsp, 1)
        self.assertEqual(shs2.tep, 12)
        self.assertEqual(shs2.deltaTL, 0)
        self.assertEqual(shs2.deltaTR, 0)

        self.assertEqual(shs1.tsp, 13)
        self.assertEqual(shs1.tep, 23)
        self.assertEqual(shs1.deltaTL, 0)
        self.assertEqual(shs1.deltaTR, 0)

        self.assertEqual(shs3.tsp, 24)
        self.assertEqual(shs3.tep, 36)
        self.assertEqual(shs3.deltaTL, 0)
        self.assertEqual(shs3.deltaTR, 200 - shs3.tep)

    def test_3_seq_t_prefered(self):
        '''
            goal: test if the sequences are wall_arranged with t_prefered
            conditions : various t_prefered that should put the sequences at the beginning, the middle and the end of the night
        '''

        print("\n===== TEST_3_SEQ_T_PREFERED =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 200

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=200, priority=1, t_prefered=11, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=0, jd2=200, priority=1, t_prefered=100, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=0, jd2=200, priority=1, t_prefered=191, duration=20)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        self.assertEqual(nbPlanned, 3)

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''

        self.scheduler.logSchedule()

        self.assertEqual(shs1.tsp, 1)
        self.assertEqual(shs1.tep, 21)
        self.assertEqual(shs1.deltaTL, 0)
        self.assertEqual(shs1.deltaTR, shs2.tsp - 1 - shs1.tep)

        self.assertEqual(shs2.tsp, 90)
        self.assertEqual(shs2.tep, 110)
        self.assertEqual(shs2.deltaTL, shs1.deltaTR)
        self.assertEqual(shs2.deltaTR, shs3.tsp - 1 - shs2.tep)

        self.assertEqual(shs3.tsp, 180)
        self.assertEqual(shs3.tep, 200)
        self.assertEqual(shs3.deltaTL, shs2.deltaTR)
        self.assertEqual(shs3.deltaTR, 0)

    def test_3_seq_t_prefered_priority(self):
        '''
            goal: test if the sequences are wall_arranged with t_prefered and priority
            conditions : various t_prefered that should put the sequences the middle of the night, according to priority
        '''

        print("\n===== TEST_3_SEQ_T_PREFERED_PRIORITY =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 200

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=200, priority=1, t_prefered=100, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=0, jd2=200, priority=0, t_prefered=100, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=0, jd2=200, priority=2, t_prefered=100, duration=20)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        self.assertEqual(nbPlanned, 3)

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''


        self.assertEqual(shs1.tsp, 69)
        self.assertEqual(shs1.tep, 89)
        self.assertEqual(shs1.deltaTL, 68)
        self.assertEqual(shs1.deltaTR, 0)

        self.assertEqual(shs2.tsp, 90)
        self.assertEqual(shs2.tep, 110)
        self.assertEqual(shs2.deltaTL, 0)
        self.assertEqual(shs2.deltaTR, 0)

        self.assertEqual(shs3.tsp, 111)
        self.assertEqual(shs3.tep, 131)
        self.assertEqual(shs3.deltaTL, 0)
        self.assertEqual(shs3.deltaTR, 200 - shs3.tep)

    def test_3_seq_move_left(self):
        '''
            goal: test if a sequence can move to the left to let another one
            conditions : use priorities to place 2 sequences with an interval between, then try to put a bigger sequence in it
        '''

        print("\n===== TEST_3_SEQ_MOVE_LEFT =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 58

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=200, priority=1, t_prefered=15, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=0, jd2=200, priority=1, t_prefered=45, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=0, jd2=200, priority=2, t_prefered=30, duration=15)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        self.assertEqual(nbPlanned, 3)

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''

        self.assertEqual(shs1.tsp, 1)
        self.assertEqual(shs1.tep, 21)
        self.assertEqual(shs1.deltaTL, 0)
        self.assertEqual(shs1.deltaTR, 0)

        self.assertEqual(shs2.tsp, 38)
        self.assertEqual(shs2.tep, 58)
        self.assertEqual(shs2.deltaTL, 0)
        self.assertEqual(shs2.deltaTR, 0)

        self.assertEqual(shs3.tsp, 22)
        self.assertEqual(shs3.tep, 37)
        self.assertEqual(shs3.deltaTL, 0)
        self.assertEqual(shs3.deltaTR, 0)

    def test_3_seq_move_right(self):
        '''
            goal: test if a sequence can move to the right to let another one
            conditions : use priorities to place 2 sequences with an interval between, then try to put a bigger sequence in it
        '''

        print("\n===== TEST_3_SEQ_MOVE_RIGHT =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 67

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=200, priority=1, t_prefered=15, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=0, jd2=200, priority=1, t_prefered=47, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=0, jd2=200, priority=2, t_prefered=30, duration=20)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        self.assertEqual(nbPlanned, 3)

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''


        self.assertEqual(shs1.tsp, 5)
        self.assertEqual(shs1.tep, 25)
        self.assertEqual(shs1.deltaTL, 4)
        self.assertEqual(shs1.deltaTR, 0)

        self.assertEqual(shs2.tsp, 47)
        self.assertEqual(shs2.tep, 67)
        self.assertEqual(shs2.deltaTL, 0)
        self.assertEqual(shs2.deltaTR, 0)

        self.assertEqual(shs3.tsp, 26)
        self.assertEqual(shs3.tep, 46)
        self.assertEqual(shs3.deltaTL, 0)
        self.assertEqual(shs3.deltaTR, 0)

    def test_3_seq_move_both(self):
        '''
            goal: test if a sequence can move to the let AND the right to let another one
            conditions : use priorities to place 2 sequences with an interval between, then try to put a bigger sequence in it
        '''

        print("\n===== TEST_3_SEQ_MOVE_BOTH =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 68

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=200, priority=1, t_prefered=15, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=0, jd2=200, priority=1, t_prefered=45, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=0, jd2=200, priority=2, t_prefered=30, duration=25)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        self.assertEqual(nbPlanned, 3)

        shs1 = next(shs for shs in shs_list if shs.sequence == seq1)
        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)
        shs3 = next(shs for shs in shs_list if shs.sequence == seq3)

        ''' checks tsp, tep, deltaTL and deltaTR for every sequence '''

        self.assertEqual(shs1.tsp, 1)
        self.assertEqual(shs1.tep, 21)
        self.assertEqual(shs1.deltaTL, 0)
        self.assertEqual(shs1.deltaTR, 0)

        self.assertEqual(shs2.tsp, 48)
        self.assertEqual(shs2.tep, 68)
        self.assertEqual(shs2.deltaTL, 0)
        self.assertEqual(shs2.deltaTR, 0)

        self.assertEqual(shs3.tsp, 22)
        self.assertEqual(shs3.tep, 47)
        self.assertEqual(shs3.deltaTL, 0)
        self.assertEqual(shs3.deltaTR, 0)

    def test_5_seq_status(self):
        '''
            goal: test the evolution of sequences status
            conditions: 5 identical sequences with different status at the beginning
        '''

        print("\n===== TEST_5_SEQ_STATUS =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 200

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=200, priority=1, t_prefered=-1, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=0, jd2=200, priority=1, t_prefered=-1, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.EXECUTED,
                                       name="seq3", jd1=0, jd2=200, priority=1, t_prefered=-1, duration=20)
        seq4 = Sequence.objects.create(request=self.req3, status=Sequence.REJECTED,
                                       name="seq4", jd1=0, jd2=200, priority=1, t_prefered=-1, duration=20)
        seq5 = Sequence.objects.create(request=self.req3, status=Sequence.UNPLANNABLE,
                                       name="seq5", jd1=0, jd2=200, priority=1, t_prefered=-1, duration=20)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        shs2 = next(shs for shs in shs_list if shs.sequence == seq2)

        seq1 = Sequence.objects.get(name="seq1")
        seq2 = Sequence.objects.get(name="seq2")
        seq3 = Sequence.objects.get(name="seq3")
        seq4 = Sequence.objects.get(name="seq4")
        seq5 = Sequence.objects.get(name="seq5")

        ''' checks sequences status '''

        self.assertEqual(nbPlanned, 2)

        self.assertEqual(seq1.status, Sequence.PLANNED)
        self.assertEqual(shs2.status, Sequence.PLANNED)
        self.assertEqual(seq3.status, Sequence.EXECUTED)
        self.assertEqual(seq4.status, Sequence.REJECTED)
        self.assertEqual(seq5.status, Sequence.UNPLANNABLE)

    def test_4_seq_eligibility(self):
        '''
            goal: test if ineligible sequences are programmed
            conditions: only ineligible sequences
        '''

        print("\n===== TEST_4_SEQ_ELIGIBILITY =====\n")

        # Check that only 1 EMPTY schedule is available in DB (because of Scheduler() instance created in setup())
        self.assertEqual(len(Schedule.objects.all()) , 1)
        sched = Schedule.objects.order_by('-created')[0]
        print("schedule is", sched)
        self.assertEqual(len(sched.shs.all()), 0)

        self.scheduler.schedule.plan_start = 100
        self.scheduler.schedule.plan_end = 200

        ''' create 4 sequences (to be planned) with default status TOBEPLANNED '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=0, jd2=110, priority=1, t_prefered=-1, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=181, jd2=300, priority=1, t_prefered=-1, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=50, jd2=90, priority=1, t_prefered=-1, duration=20)
        seq4 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq4", jd1=300, jd2=400, priority=1, t_prefered=-1, duration=20)
        #for s in (seq1,seq2,seq3,seq4): print(s.status)

        # Check that we now have exactly 4 sequences in DB
        self.assertEqual(len(Sequence.objects.all()) , 4)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        # Check that still only 1 schedule available in DB, and 0 sequence in it
        self.assertEqual(len(Schedule.objects.all()) , 1)
        # Get the last (more recent) schedule saved by makeSchedule()
        sched = Schedule.objects.order_by('-created')[0]
        print("updated schedule is", sched, "with night start", sched.plan_night_start)
        shs_list = sched.shs.all()
        # EP added
        self.assertEqual(len(shs_list), 0)
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])
        self.assertEqual(nbPlanned, 0)

        ''' checks sequences status '''
        seq1 = Sequence.objects.get(name="seq1")
        seq2 = Sequence.objects.get(name="seq2")
        seq3 = Sequence.objects.get(name="seq3")
        seq4 = Sequence.objects.get(name="seq4")

        for s in (seq1,seq2,seq3,seq4): print(s.status)
        self.assertEqual(seq1.status, Sequence.UNPLANNABLE)
        self.assertEqual(seq2.status, Sequence.TOBEPLANNED)
        self.assertEqual(seq3.status, Sequence.UNPLANNABLE)
        self.assertEqual(seq4.status, Sequence.TOBEPLANNED)


    def test_invalid_sequences(self):
        '''
            goal: test if the scheduler is able to plan invalid sequences (it shouldn't)
        '''

        print("\n===== TEST_INVALID_SEQUENCES =====\n")

        self.scheduler.schedule.plan_start = 0
        self.scheduler.schedule.plan_end = 200

        ''' create the sequences '''
        seq1 = Sequence.objects.create(request=self.req1, status=Sequence.TOBEPLANNED,
                                       name="seq1", jd1=190, jd2=110, priority=1, t_prefered=-1, duration=20)
        seq2 = Sequence.objects.create(request=self.req2, status=Sequence.TOBEPLANNED,
                                       name="seq2", jd1=20, jd2=30, priority=1, t_prefered=-1, duration=20)
        seq3 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq3", jd1=50, jd2=90, priority=1, t_prefered=-1, duration=0)
        seq4 = Sequence.objects.create(request=self.req3, status=Sequence.TOBEPLANNED,
                                       name="seq4", jd1=50, jd2=90, priority=1, t_prefered=-1, duration=-10)

        ''' compute and print the schedule '''
        self.scheduler.makeSchedule()

        sched = Schedule.objects.order_by('-created')[0]
        shs_list = sched.shs.all()
        nbPlanned = len([shs for shs in shs_list if shs.status == Sequence.PLANNED])

        seq1 = Sequence.objects.get(name="seq1")
        seq2 = Sequence.objects.get(name="seq2")
        seq3 = Sequence.objects.get(name="seq3")
        seq4 = Sequence.objects.get(name="seq4")

        ''' checks sequences status '''

        self.assertEqual(seq1.status, Sequence.INVALID)
        self.assertEqual(seq2.status, Sequence.INVALID)
        self.assertEqual(seq3.status, Sequence.INVALID)
        self.assertEqual(seq4.status, Sequence.INVALID)
        self.assertEqual(nbPlanned, 0)

    def test_simulation(self):
        '''
            goal : Uses the simulation module to make a schedule and test the validity of created sequences
        '''

        print("\n===== TEST_SIMULATION =====\n")

        simulator = Simulator()
        simulator.simulate(SIMULATION_FILE)