class TestParameters(TestCase): def setUp(self): self.parametersObj = Parameters() self.parametersObj.WITH_SHIFTS = True rand = Random() rand.initialization() def tearDown(self): self.parametersObj = None def test_getTotalTime(self): shift_duration = [5, 9, 2, 1] shift_type = [ Constants.ENTREGA, Constants.ENTREGA, Constants.RECOGIDA, Constants.DUAL ] shift_factor = 3600 # hours self.parametersObj.setParameters(shift_duration, shift_type, shift_factor) self.assertEqual(self.parametersObj.getTotalTime(Constants.ENTREGA), 14, "The delivery time should be 5 + 9") self.assertEqual(self.parametersObj.getTotalTime(Constants.RECOGIDA), 2, "The collection time should be 2") self.assertEqual(self.parametersObj.getTotalTime(Constants.DUAL), 1, "The dual time should be 1") def test_getCurrentShift_Not_Edges(self): shift_duration = [5, 9, 2, 1] # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # E E E E E E E E E E E E E E R R D shift_type = [ Constants.ENTREGA, Constants.ENTREGA, Constants.RECOGIDA, Constants.DUAL ] shift_factor = 3600 # hours self.parametersObj.setParameters(shift_duration, shift_type, shift_factor) self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 2 * 3600), Constants.ENTREGA, "The shift should be ENTREGA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 7 * 3600), Constants.ENTREGA, "The shift should be ENTREGA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 15 * 3600), Constants.RECOGIDA, "The shift should be RECOGIDA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 17 * 3600), Constants.DUAL, "The shift should be DUAL") def test_getCurrentShift_Edges(self): shift_duration = [5, 9, 2, 1] # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # E E E E E E E E E E E E E E R R D shift_type = [ Constants.ENTREGA, Constants.ENTREGA, Constants.RECOGIDA, Constants.DUAL ] shift_factor = 3600 # hours self.parametersObj.setParameters(shift_duration, shift_type, shift_factor) self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 0 * 3600), Constants.ENTREGA, "The shift should be ENTREGA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 13 * 3600), Constants.ENTREGA, "The shift should be ENTREGA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 14 * 3600), Constants.RECOGIDA, "The shift should be RECOGIDA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 15 * 3600), Constants.RECOGIDA, "The shift should be RECOGIDA") self.assertEqual( self.parametersObj.getCurrentShift( Constants.SIMULATION_INITIAL_TIME + 16 * 3600), Constants.DUAL, "The shift should be DUAL")
class Core: # CLASS FUNCTIONS def __init__(self, parameters=None): if parameters is None: self.parameters = Parameters() else: self.parameters = parameters num_sources = Constants.DEFAULT_SOURCES num_processors = self.parameters.num_processors # Attributes initialization self.processors = [] self.sources = [] self.eventsList = PriorityQueue(0) # maxsize = 0 (infinite) self.previousTime = Constants.SIMULATION_INITIAL_TIME self.currentTime = Constants.SIMULATION_INITIAL_TIME self.idleProcessors = 0 self.serviceProcessors = 0 self.entitiesSystem = 0 self.service_per_shift = [] self.service_per_total = [] self.shift_durations = self.parameters.getParameters()[1] self.shift_next_time = self.shift_durations[0] self.shift_next_index = 1 # Instance creation self.queue = Queue(Constants.SLOTS_BUFFER) self.parking = Queue(Constants.SLOTS_QUEUE) self.random = Random() for _ in range(0, num_processors): self.processors.append(Processor(self)) for _ in range(0, num_sources): self.sources.append(Source(self)) # Dependency injection for source in self.sources: source.addOutput(self.queue) # source -> queue self.queue.addOutput(self.parking) # queue -> parking self.parking.addInput(self.queue) # parking <- queue for processor in self.processors: self.parking.addOutput(processor) # parking -> processor processor.addInput(self.parking) # processor <- parking self.output_file = None self.numberOfIdleProcessors = num_processors def increaseEntitiesSystem(self): self.entitiesSystem += 1 def decreaseEntitiesSystem(self): self.entitiesSystem -= 1 def startSimulation(self): """Implemented by all modules""" startEvent = Event(self, Constants.START_SIMULATION, self.currentTime, self.currentTime) self.logEvent(startEvent) for source in self.sources: source.startSimulation() def endSimulation(self): """Implemented by all modules""" endEvent = Event( self, # eventCreator Constants.END_SIMULATION, # eventName self.currentTime, # eventScheduled self.currentTime # eventTime ) self.logEvent(endEvent) self.updateState(endEvent) def executeEvent(self, currentEvent): """Implemented by all event creator modules""" if currentEvent.eventName == Constants.START_SIMULATION: self.startSimulation() def run(self): self.logHeaders() # creates output file with flag w+ with open(self.parameters.output_file + '.csv', "a+") as self.output_file: self.startSimulation() while not self.eventsList.empty(): currentEvent = self.eventsList.get() self.updateState(currentEvent) self.logEvent(currentEvent) currentEvent.executeEvent() self.endSimulation() self.stats() def addEvent(self, addedEvent): self.eventsList.put(addedEvent, addedEvent.eventTime) def getCurrentTime(self): return self.currentTime def updateState(self, event): self.previousTime = self.currentTime self.currentTime = event.eventTime timeStep = self.currentTime - self.previousTime self.numberOfIdleProcessors = 0 for processor in self.processors: if processor.isIdle(): self.idleProcessors += timeStep self.numberOfIdleProcessors += 1 else: self.serviceProcessors += timeStep if self.currentTime > self.shift_next_time * 3600: if self.shift_next_index < len(self.shift_durations): self.shift_next_time += self.shift_durations[ self.shift_next_index] self.shift_next_index += 1 if not self.service_per_shift: # first shift - empty list; if == 0 self.service_per_shift.append(self.serviceProcessors) else: self.service_per_shift.append(self.serviceProcessors - self.service_per_total[-1]) self.service_per_total.append(self.serviceProcessors) if event.eventName == Constants.END_SIMULATION and len( self.service_per_shift) < len(self.shift_durations): # print('END_SIMULATION') self.service_per_shift.append(self.serviceProcessors - self.service_per_total[-1]) def getCurrentShift(self): return self.parameters.getCurrentShift(self.currentTime) def logHeaders(self): s = 'Current_Time,' s += 'Event_Name,' s += 'Event_Scheduled,' s += 'Event-Time,' s += 'Idle_Processors,' s += 'Service_Processors,' s += 'Number_Idle_Processors,' s += 'Buffer_Length,' s += 'Queue_Length,' s += 'Entities_System,' s += 'Shift' with open(self.parameters.output_file + '.csv', "w+") as output_file: output_file.write(s + '\n') def logEvent(self, currentEvent): s = str(self.currentTime) + ',' s += currentEvent.eventName + ',' s += str(currentEvent.eventScheduled) + ',' s += str(currentEvent.eventTime) + ',' s += str(self.idleProcessors) + ',' s += str(self.serviceProcessors) + ',' s += str(self.numberOfIdleProcessors) + ',' s += str(self.queue.getQueueLength()) + ',' s += str(self.parking.getQueueLength()) + ',' s += str(self.entitiesSystem) + ',' s += str(self.parameters.getCurrentShift(currentEvent.eventScheduled)) self.output_file.write(s + '\n') def stats(self): s = 'Max_Queue_Length' r = str(self.parking.getMaxQueueLength()) s += ',Processors_Capacity_Used' r += ',' + str( round( 100 * self.serviceProcessors / (self.parameters.num_processors * Constants.SIMULATION_DURATION), 2)) # in % shift_type, shift_duration = self.parameters.getParameters() for idx in range(len(shift_type)): s += ',Shift_Type' r += ',' + shift_type[idx] s += ',Shift_Duration' r += ',' + str(shift_duration[idx]) s += ',Shift_Capacity_Usage' r += ',' + str( round( 100 * self.service_per_shift[idx] / (self.parameters.num_processors * self.shift_durations[idx] * 3600), 2)) with open(self.parameters.output_file + '.stats.csv', "w+") as output_file: output_file.write(s + '\n') output_file.write(r + '\n')