def run_simulation(self):
        """ Runs the simulation, either with a scheduler or by waiting to trigger
            each event. 

            With the event_lock method, we wait of an event to happend with a 
            timeout set to the delay until the next event. The event should be 
            triggered when all current downloads are over, which means that nothing
            is happening any more in the simulation. This happens only when the 
            skip_inactivity is set to True.

            With the scheduler method, when not skiping inactivity, we just run 
            the already filled and configured scheduler object. The option to skip
            inactivity should not be used as it is using a lot of CPU for nothing. 
        """
        try:
            if self.method == 'event_lock':

                if self.skip_inactivity:
                    simu.action_when_zero = self.signal_sys_inact

                while not self._events_queue.empty():
                    event = self._events_queue.get()
                    print("New event: "+str(event))
                    self._req_event.clear()

                    if not self.skip_inactivity or not simu.no_active_download():
                        self._req_event.wait(event['delay'])

                    self._clients[event['id_client']].request_media(event['id_video'], event['id_server'])

            elif self.method == 'scheduler':
                if self.skip_inactivity:
                    while True:
                        """ Inefficient way to skip the inactivity """
                        next = self._scheduler.run(False)
                        # have a threshold to avoid testing the inavtivity all the time
                        if next != None:
                            if next/config.speed >= 1:
                                # if it takes more than 1 second in real time
                                if simu.no_active_download(self._clients.values()):
                                    simu.add_time(next-1)
                                    print("Skiping inactivity!")
                        elif self._scheduler.empty():
                            return
                        else:
                            simu.sleep(next/2)
                else:
                    self._scheduler.run()
            else:
                print("run_simulation error: no method specified!")
        except (KeyboardInterrupt, SystemExit):
            print(' ')
            print("Simulation interupted. To exit, press ctrl+c again.")
            print(' ')
    def wait_end(self):
        """ Waits for for all downloads to be over """
        print("The end.")

        while not simu.no_active_download(self._clients.values()):
            print("Waiting...")
            time.sleep(1)
    def test_no_active_download(self):
        self.s1 = VideoServer(1, "s1")
        self.c1 = LatenciesClient(1001, "c1")
        self.c1.set_func_new_dl(simu.inc_nb_dl)
        self.c1.set_func_end_dl(simu.dec_nb_dl)
        
        self.c2 = LatenciesClient(1002, "c2")
        self.c2.set_func_new_dl(simu.inc_nb_dl)
        self.c2.set_func_end_dl(simu.dec_nb_dl)

        # we set the chunk to a big size so that we can determine accurately the download time
        self.c1.connect_to(self.s1).set_lag(0.1).set_bandwidth(1024).set_max_chunk(32)
        self.s1.connect_to(self.c1).set_lag(0.1).set_bandwidth(1024).set_max_chunk(32)

        self.video = {'idVideo': 1337, 'duration': 60, 'size': 2048, 'bitrate': 2048/60, 'title': 'Video', 'description': 'A video'}
        self.s1.add_video(video=self.video)

        self.c1.request_media(1337, 2)

        self.assertFalse(simu.no_active_download((self.c1, self.c2)))

        simu.sleep(3)

        self.assertTrue(simu.no_active_download((self.c1, self.c2)))
 def signal_sys_inact(self):
     """ function to signal that the system is currently inactive (no downloads)
     """
     if simu.no_active_download():
         # to be sure
         self.signal_req_event()