first changes, topology09 running

parent f9392dab
......@@ -25,15 +25,18 @@ Created on 12 Jul 2012
Class that acts as an abstract. It should have no instances. All the core-objects should inherit from it
'''
from SimPy.Simulation import Process, Resource, now, SimEvent, waitevent
# from SimPy.Simulation import Process, Resource, now, SimEvent, waitevent
import simpy
# ===========================================================================
# the core object
# ===========================================================================
class CoreObject(Process):
class CoreObject(object):
def __init__(self, id, name, **kw):
Process.__init__(self)
from Globals import G
self.env=G.env
# Process.__init__(self)
self.id = id
self.objName = name
# lists that hold the previous and next objects in the flow
......@@ -54,14 +57,18 @@ class CoreObject(Process):
self.interruptCause=None
self.gatherWipStat=False
# signalizing an event that activates the generator
self.isRequested=SimEvent('isRequested')
self.canDispose=SimEvent('canDispose')
self.interruptionEnd=SimEvent('interruptionEnd')
self.interruptionStart=SimEvent('interruptionStart')
# self.isRequested=SimEvent('isRequested')
self.isRequested=self.env.event()
# self.canDispose=SimEvent('canDispose')
self.canDispose=self.env.event()
# self.interruptionEnd=SimEvent('interruptionEnd')
self.interruptionEnd=self.env.event()
# self.interruptionStart=SimEvent('interruptionStart')
self.interruptionStart=self.env.event()
def initialize(self):
# XXX why call super.__init__ outside of __init__ ?
Process.__init__(self)
# Process.__init__(self)
self.Up=True #Boolean that shows if the machine is in failure ("Down") or not ("up")
self.onShift=True
self.currentEntity=None
......@@ -133,10 +140,14 @@ class CoreObject(Process):
# TODO, this should be also updated in Globals.setWIP (in case we have initial wip)
self.wipStatList=[[0,0]]
# signalizing an event that activates the generator
self.isRequested=SimEvent('isRequested')
self.canDispose=SimEvent('canDispose')
self.interruptionEnd=SimEvent('interruptionEnd')
self.interruptionStart=SimEvent('interruptionStart')
# self.isRequested=SimEvent('isRequested')
self.isRequested=self.env.event()
# self.canDispose=SimEvent('canDispose')
self.canDispose=self.env.event()
# self.interruptionEnd=SimEvent('interruptionEnd')
self.interruptionEnd=self.env.event()
# self.interruptionStart=SimEvent('interruptionStart')
self.interruptionStart=self.env.event()
# =======================================================================
# the main process of the core object
......@@ -167,7 +178,7 @@ class CoreObject(Process):
def removeEntity(self, entity=None):
self.addBlockage()
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
activeObjectQueue.remove(entity) #remove the Entity from the queue
if self.receiver:
self.receiver.appendEntity(entity)
......@@ -176,11 +187,11 @@ class CoreObject(Process):
self.downTimeInTryingToReleaseCurrentEntity=0
self.offShiftTimeTryingToReleaseCurrentEntity=0
self.timeLastEntityLeft=now()
self.timeLastEntityLeft=self.env.now
self.outputTrace(entity.name, "released "+self.objName)
# update wipStatList
if self.gatherWipStat:
self.wipStatList.append([now(), len(activeObjectQueue)])
self.wipStatList.append([self.env.now, len(activeObjectQueue)])
return entity
#===========================================================================
......@@ -188,7 +199,7 @@ class CoreObject(Process):
# this method is created to be overridden by the Assembly class in its getEntity where Frames are loaded
#===========================================================================
def appendEntity(self,entity=None):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
activeObjectQueue.append(entity)
# =======================================================================
......@@ -205,11 +216,11 @@ class CoreObject(Process):
# each time an Entity is removed
# =======================================================================
def addBlockage(self):
self.totalTimeInCurrentEntity=now()-self.timeLastEntityEntered
self.totalTimeInCurrentEntity=self.env.now-self.timeLastEntityEntered
self.totalTimeWaitingForOperator += self.operatorWaitTimeCurrentEntity
if self.timeLastEntityEnded<self.timeLastShiftStarted:
self.offShiftTimeTryingToReleaseCurrentEntity=self.timeLastShiftStarted-self.timeLastShiftEnded
blockage=now()-(self.timeLastEntityEnded+self.downTimeInTryingToReleaseCurrentEntity+self.offShiftTimeTryingToReleaseCurrentEntity)
blockage=self.env.now-(self.timeLastEntityEnded+self.downTimeInTryingToReleaseCurrentEntity+self.offShiftTimeTryingToReleaseCurrentEntity)
self.totalBlockageTime+=blockage
# =======================================================================
......@@ -219,12 +230,12 @@ class CoreObject(Process):
# get active object and its queue, as well as the active (to be) entity
#(after the sorting of the entities in the queue of the giver object)
# activeObject=self.getActiveObject()
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
# get giver object, its queue, and sort the entities according to this object priorities
giverObject=self.giver
giverObject.sortEntities() #sort the Entities of the giver
#according to the scheduling rule if applied
giverObjectQueue=giverObject.Res.activeQ
giverObjectQueue=giverObject.Res.users
# if the giverObject is blocked then unBlock it
if giverObject.exitIsAssignedTo():
giverObject.unAssignExit()
......@@ -242,10 +253,10 @@ class CoreObject(Process):
#append the time to schedule so that it can be read in the result
#remember that every entity has it's schedule which is supposed to be updated every time
# he entity enters a new object
activeEntity.schedule.append([self,now()])
activeEntity.schedule.append([self,self.env.now])
#update variables
activeEntity.currentStation=self
self.timeLastEntityEntered=now()
self.timeLastEntityEntered=self.env.now
self.nameLastEntityEntered=activeEntity.name # this holds the name of the last entity that got into Machine
self.downTimeProcessingCurrentEntity=0
# update the next list of the object
......@@ -265,7 +276,7 @@ class CoreObject(Process):
# and if preemption is required
#===========================================================================
def preemptReceiver(self):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
# find a critical order if any
critical=False
......@@ -296,13 +307,13 @@ class CoreObject(Process):
# if the obtained Entity is critical and the receiver is preemptive and not operated
# in the case that the receiver is operated the preemption is performed by the operators
# if the receiver is not Up then no preemption will be performed
if not receiverOperated and len(receiver.Res.activeQ)>0:
if not receiverOperated and len(receiver.Res.users)>0:
#if the receiver does not hold an Entity that is also critical
if not receiver.Res.activeQ[0].isCritical:
if not receiver.Res.users[0].isCritical:
receiver.shouldPreempt=True
# self.printTrace(self.id, preempt=receiver.id)
receiver.preempt()
receiver.timeLastEntityEnded=now() #required to count blockage correctly in the preemptied station
receiver.timeLastEntityEnded=self.env.now #required to count blockage correctly in the preemptied station
# sort so that the critical entity is placed in front
activeObjectQueue.sort(key=lambda x: x==activeEntity, reverse=True)
# if there is a critical entity and the possible receivers are operated then signal the Router
......@@ -311,7 +322,7 @@ class CoreObject(Process):
activeObjectQueue.sort(key=lambda x: x==activeEntity, reverse=True)
# update wipStatList
if self.gatherWipStat:
self.wipStatList.append([now(), len(activeObjectQueue)])
self.wipStatList.append([self.env.now, len(activeObjectQueue)])
#===========================================================================
......@@ -364,7 +375,7 @@ class CoreObject(Process):
# self.printTrace(self.id, signalReceiver=self.receiver.id)
# assign the entry of the receiver
self.receiver.assignEntryTo()
self.receiver.isRequested.signal(self)
self.receiver.isRequested.succeed(self)
return True
# if no receiver can accept then try to preempt a receive if the stations holds a critical order
self.preemptReceiver()
......@@ -379,8 +390,9 @@ class CoreObject(Process):
# dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject)
maxTimeWaiting=0 # dummy variable counting the time a successor is waiting
receiver=None
from Globals import G
for object in candidates:
timeWaiting=now()-object.timeLastEntityLeft # the time it has been waiting is updated and stored in dummy variable timeWaiting
timeWaiting=G.env.now-object.timeLastEntityLeft # the time it has been waiting is updated and stored in dummy variable timeWaiting
if(timeWaiting>maxTimeWaiting or maxTimeWaiting==0):# if the timeWaiting is the maximum among the ones of the successors
maxTimeWaiting=timeWaiting
receiver=object # set the receiver as the longest waiting possible receiver
......@@ -394,13 +406,13 @@ class CoreObject(Process):
# if an operator is not assigned to the receiver then do not signal the receiver but the Router
try:
if not receiver.assignedOperator or\
(receiver.isPreemptive and len(receiver.Res.activeQ)>0):
(receiver.isPreemptive and len(receiver.Res.users)>0):
if receiver.isLoadRequested():
from Globals import G
if not G.Router.invoked:
# self.printTrace(self.id, signal='router')
G.Router.invoked=True
G.Router.isCalled.signal(now())
G.Router.isCalled.succeed(self.env.now)
return True
else:
return False
......@@ -454,7 +466,7 @@ class CoreObject(Process):
self.giver=giver
self.giver.receiver=self
# self.printTrace(self.id, signalGiver=self.giver.id)
self.giver.canDispose.signal(self)
self.giver.canDispose.succeed(self)
return True
return False
......@@ -467,12 +479,13 @@ class CoreObject(Process):
# dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject)
maxTimeWaiting=0 # dummy variable counting the time a predecessor is blocked
giver=None
from Globals import G
# loop through the possible givers to see which have to dispose and which is the one blocked for longer
for object in candidates:
if(object.downTimeInTryingToReleaseCurrentEntity>0):# and the predecessor has been down while trying to give away the Entity
timeWaiting=now()-object.timeLastFailureEnded # the timeWaiting dummy variable counts the time end of the last failure of the giver object
timeWaiting=self.env.now-object.timeLastFailureEnded # the timeWaiting dummy variable counts the time end of the last failure of the giver object
else:
timeWaiting=now()-object.timeLastEntityEnded # in any other case, it holds the time since the end of the Entity processing
timeWaiting=G.env.now-object.timeLastEntityEnded # in any other case, it holds the time since the end of the Entity processing
#if more than one predecessor have to dispose take the part from the one that is blocked longer
if(timeWaiting>=maxTimeWaiting):
giver=object # the object to deliver the Entity to the activeObject is set to the ith member of the previous list
......@@ -493,7 +506,7 @@ class CoreObject(Process):
from Globals import G
if(G.trace=="Yes"): #output only if the user has selected to
#handle the 3 columns
G.traceSheet.write(G.traceIndex,0,str(now()))
G.traceSheet.write(G.traceIndex,0,str(self.env.now))
G.traceSheet.write(G.traceIndex,1,entityName)
G.traceSheet.write(G.traceIndex,2,message)
G.traceIndex+=1 #increment the row
......@@ -509,7 +522,7 @@ class CoreObject(Process):
assert len(kw)==1, 'only one phrase per printTrace supported for the moment'
from Globals import G
import Globals
time=now()
time=self.env.now
charLimit=60
remainingChar=charLimit-len(entity)-len(str(time))
if(G.console=='Yes'):
......@@ -549,7 +562,7 @@ class CoreObject(Process):
# checks if the Object can dispose an entity to the following object
# =======================================================================
def haveToDispose(self, callerObject=None):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
return len(activeObjectQueue)>0
# =======================================================================
......@@ -581,7 +594,7 @@ class CoreObject(Process):
# get the activeQ of the active object.
# =======================================================================
def getActiveObjectQueue(self):
return self.Res.activeQ
return self.Res.users
# =======================================================================
# get the giver object in a getEntity transaction.
......@@ -593,7 +606,7 @@ class CoreObject(Process):
# get the giver object queue in a getEntity transaction.
# =======================================================================
def getGiverObjectQueue(self):
return self.giver.Res.activeQ
return self.giver.Res.users
# =======================================================================
# get the receiver object in a removeEntity transaction.
......@@ -605,7 +618,7 @@ class CoreObject(Process):
# get the receiver object queue in a removeEntity transaction.
# =======================================================================
def getReceiverObjectQueue(self):
return self.receiver.Res.activeQ
return self.receiver.Res.users
# =======================================================================
# calculates the processing time
......@@ -674,7 +687,7 @@ class CoreObject(Process):
# false if object holds entities in its queue
#===========================================================================
def activeQueueIsEmpty(self):
return len(self.Res.activeQ)==0
return len(self.Res.users)==0
# =======================================================================
# actions to be carried out when the processing of an Entity ends
......@@ -686,5 +699,5 @@ class CoreObject(Process):
# check if an entity is in the internal Queue of the object
#===========================================================================
def isInActiveQueue(self, entity=None):
activeObjectQueue = self.Res.activeQ
activeObjectQueue = self.Res.users
return any(x==entity for x in activeObjectQueue)
......@@ -25,7 +25,8 @@ Created on 6 Feb 2013
models the exit of the model
'''
from SimPy.Simulation import now, Process, Resource, infinity, waituntil, waitevent
# from SimPy.Simulation import now, Process, Resource, infinity, waituntil, waitevent
import simpy
import xlwt
from CoreObject import CoreObject
......@@ -54,7 +55,7 @@ class Exit(CoreObject):
CoreObject.initialize(self)
# initialize the internal Queue (type Resource) of the Exit
self.Res=Resource(capacity=infinity)
self.Res=simpy.Resource(self.env, capacity=10000)
# The number of resource that exited through this exit.
# XXX bug: cannot output as json when nothing has exited.
self.numOfExits=0
......@@ -68,7 +69,8 @@ class Exit(CoreObject):
def run(self):
while 1:
# wait until the Queue can accept an entity and one predecessor requests it
yield waitevent, self, self.isRequested
yield self.isRequested
self.isRequested=self.env.event()
# TODO: insert extra controls to check whether the self.giver attribute is correctly updated
self.getEntity()
......@@ -109,13 +111,13 @@ class Exit(CoreObject):
# if activeEntity in G.EntityList:
# G.EntityList.remove(activeEntity)
# self.clear(activeEntity)
self.totalLifespan+=now()-activeEntity.startTime #Add the entity's lifespan to the total one.
self.totalLifespan+=self.env.now-activeEntity.startTime #Add the entity's lifespan to the total one.
self.numOfExits+=1 # increase the exits by one
self.totalNumberOfUnitsExited+=activeEntity.numberOfUnits # add the number of units that xited
self.totalTaktTime+=now()-self.timeLastEntityLeft # add the takt time
self.timeLastEntityLeft=now() # update the time that the last entity left from the Exit
self.totalTaktTime+=self.env.now-self.timeLastEntityLeft # add the takt time
self.timeLastEntityLeft=self.env.now # update the time that the last entity left from the Exit
activeObjectQueue=self.getActiveObjectQueue()
del self.Res.activeQ[:]
del self.Res.users[:]
return activeEntity
@staticmethod
......
......@@ -40,7 +40,8 @@ import numpy
numpy.seterr(all='raise')
from SimPy.Simulation import activate, initialize, simulate, now, infinity
# from SimPy.Simulation import activate, initialize, simulate, now, infinity
import simpy
from Globals import G
from Source import Source
from Machine import Machine
......@@ -885,11 +886,14 @@ def initializeObjects():
# ===========================================================================
def activateObjects():
for element in G.ObjList:
activate(element, element.run())
# activate(element, element.run())
G.env.process(element.run())
for ev in G.EventGeneratorList:
activate(ev, ev.run())
# activate(ev, ev.run())
G.env.process(ev.run())
for oi in G.ObjectInterruptionList:
activate(oi, oi.run())
# activate(oi, oi.run())
G.env.process(oi.run())
# ===========================================================================
# reads the WIP of the stations
......@@ -1261,6 +1265,7 @@ def main(argv=[], input_data=None):
#read the input from the JSON file and create the line
G.JSONData=json.loads(G.InputData) # create the dictionary JSONData
readGeneralInput()
G.env=simpy.Environment() # initialize the environment
createObjects()
createObjectInterruptions()
setTopology()
......@@ -1272,7 +1277,7 @@ def main(argv=[], input_data=None):
G.Rnd=Random('%s%s' % (G.seed, i))
else:
G.Rnd=Random()
initialize() #initialize the simulation
# initialize() #initialize the simulation
createWIP()
initializeObjects()
Globals.setWIP(G.EntityList)
......@@ -1281,22 +1286,24 @@ def main(argv=[], input_data=None):
# if the simulation is ran until no more events are scheduled,
# then we have to find the end time as the time the last entity ended.
if G.maxSimTime==-1:
simulate(until=infinity) # simulate until there are no more events.
# If someone does it for a model that has always events, then it will run forever!
G.env.run(until=infinity)
# simulate(until=infinity) # simulate until there are no more events.
# # If someone does it for a model that has always events, then it will run forever!
# # identify from the exits what is the time that the last entity has ended.
# endList=[]
# for exit in G.ExitList:
# endList.append(exit.timeLastEntityLeft)
# G.maxSimTime=float(max(endList))
# identify the time of the last event
if now()!=0: #do not let G.maxSimTime=0 so that there will be no crash
G.maxSimTime=now()
if G.env.now!=0: #do not let G.maxSimTime=0 so that there will be no crash
G.maxSimTime=env.now
else:
print "simulation ran for 0 time, something may have gone wrong"
logger.info("simulation ran for 0 time, something may have gone wrong")
#else we simulate until the given maxSimTime
else:
simulate(until=G.maxSimTime) #simulate until the given maxSimTime
else:
G.env.run(until=G.maxSimTime)
# simulate(until=G.maxSimTime) #simulate until the given maxSimTime
#carry on the post processing operations for every object in the topology
for element in G.ObjList:
......
......@@ -25,8 +25,9 @@ Created on 8 Nov 2012
Models a machine that can also have failures
'''
from SimPy.Simulation import Process, Resource, SimEvent
from SimPy.Simulation import activate, passivate, waituntil, now, hold, request, release, waitevent
# from SimPy.Simulation import Process, Resource, SimEvent
# from SimPy.Simulation import activate, passivate, waituntil, now, hold, request, release, waitevent
import simpy
from Failure import Failure
from CoreObject import CoreObject
......@@ -150,12 +151,14 @@ class Machine(CoreObject):
self.isPreemptive=isPreemptive
self.resetOnPreemption=resetOnPreemption
# events used by the broker
self.brokerIsSet=SimEvent('brokerIsSet')
# self.brokerIsSet=SimEvent('brokerIsSet')
self.brokerIsSet=self.env.event()
# this event is generated every time an operator is requested by machine for Load operation type.
# if the machine has not succeeded in getting an entity due to the resource absence
# and waits for the next event to get the entity,
# then it must be signalled that the operator is now available
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
# flag notifying that there is operator assigned to the actievObject
self.assignedOperator=True
......@@ -166,7 +169,8 @@ class Machine(CoreObject):
# using the Process __init__ and not the CoreObject __init__
CoreObject.initialize(self)
# initialize the internal Queue (type Resource) of the Machine
self.Res=Resource(self.capacity)
#self.Res=Resource(self.capacity)
self.Res=simpy.Resource(self.env, capacity=1)
# initiate the Broker responsible to control the request/release
# initialize the operator pool if any
if (self.operatorPool!="None"):
......@@ -211,12 +215,14 @@ class Machine(CoreObject):
# flag notifying that there is operator assigned to the actievObject
self.assignedOperator=True
self.brokerIsSet=SimEvent('brokerIsSet')
# self.brokerIsSet=SimEvent('brokerIsSet')
self.brokerIsSet=self.env.event()
# this event is generated every time an operator is requested by machine for Load operation type.
# if the machine has not succeeded in getting an entity due to the resource absence
# and waits for the next event to get the entity,
# then it must be signalled that the operator is now available
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
# =======================================================================
# the main process of the machine
......@@ -229,23 +235,29 @@ class Machine(CoreObject):
# waitEvent isRequested /interruptionEnd/loadOperatorAvailable
while 1:
# self.printTrace(self.id, waitEvent='')
yield waitevent, self, [self.isRequested, self.interruptionEnd, self.loadOperatorAvailable]
# yield waitevent, self, [self.isRequested, self.interruptionEnd, self.loadOperatorAvailable]
receivedEvent = yield self.isRequested | self.interruptionEnd | self.loadOperatorAvailable
# self.printTrace(self.id, received='')
# if the machine can accept an entity and one predecessor requests it continue with receiving the entity
if self.isRequested.signalparam:
# self.printTrace(self.id, isRequested=self.isRequested.signalparam.id)
assert self.isRequested.signalparam==self.giver, 'the giver is not the requestingObject'
if self.isRequested in receivedEvent:
# self.printTrace(self.id, isRequested=self.isRequested.value.id)
assert self.isRequested.value==self.giver, 'the giver is not the requestingObject'
assert self.giver.receiver==self, 'the receiver of the signalling object in not the station'
# reset the signalparam of the isRequested event
self.isRequested.signalparam=None
# self.isRequested.value=None
self.isRequested=self.env.event()
break
# if an interruption caused the control to be taken by the machine or
# if an operator was rendered available while it was needed by the machine to proceed with getEntity
if self.interruptionEnd.signalparam==now() or self.loadOperatorAvailable.signalparam==now():
# if self.interruptionEnd.signalparam==now():
# self.printTrace(self.id, interruptionEnd=str(self.interruptionEnd.signalparam))
# elif self.loadOperatorAvailable.signalparam==now():
# self.printTrace(self.id,loadOperatorAvailable=str(self.loadOperatorAvailable.signalparam))
if self.interruptionEnd.value==self.env.now or self.loadOperatorAvailable.value==self.env.now:
if self.interruptionEnd in receivedEvent:
self.interruptionEnd=self.env.event()
if self.loadOperatorAvailable in receivedEvent:
self.loadOperatorAvailable=self.env.event()
# if self.interruptionEnd.value==self.env.now:
# self.printTrace(self.id, interruptionEnd=str(self.interruptionEnd.value))
# elif self.loadOperatorAvailable.value==self.env.now:
# self.printTrace(self.id,loadOperatorAvailable=str(self.loadOperatorAvailable.value))
# try to signal the Giver, otherwise wait until it is requested
if self.signalGiver():
break
......@@ -264,19 +276,20 @@ class Machine(CoreObject):
# when it's ready to accept (canAcceptAndIsRequested) then inform the broker
# machines waits to be operated (waits for the operator)
self.requestOperator()
self.timeWaitForLoadOperatorStarted = now()
self.timeWaitForLoadOperatorStarted = self.env.now
# wait until the Broker has waited times equal to loadTime (if any)
yield waitevent, self, self.brokerIsSet
self.timeWaitForLoadOperatorEnded = now()
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
self.timeWaitForLoadOperatorEnded = self.env.now
self.loadOperatorWaitTimeCurrentEntity += self.timeWaitForLoadOperatorEnded-self.timeWaitForLoadOperatorStarted
self.totalTimeWaitingForLoadOperator += self.loadOperatorWaitTimeCurrentEntity
# ======= Load the machine if the Load is defined as one of the Operators' operation types
if any(type=="Load" for type in self.multOperationTypeList) and self.isOperated():
self.timeLoadStarted = now()
yield hold,self,self.calculateLoadTime()
self.timeLoadStarted = self.env.now
yield self.env.timeout(self.calculateLoadTime())
# TODO: if self.interrupted(): There is the issue of failure during the Loading
self.timeLoadEnded = now()
self.timeLoadEnded = self.env.now
self.loadTimeCurrentEntity = self.timeLoadEnded-self.timeLoadStarted
self.totalLoadTime += self.loadTimeCurrentEntity
......@@ -290,7 +303,8 @@ class Machine(CoreObject):
# machine has to release the operator
self.releaseOperator()
# wait until the Broker has finished processing
yield waitevent, self, self.brokerIsSet
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# TODO: reset the requestinEntity before receiving the currentEntity
self.requestingEntity=None
......@@ -310,10 +324,11 @@ class Machine(CoreObject):
# when it's ready to accept (canAcceptAndIsRequested) then inform the broker
# machines waits to be operated (waits for the operator)
self.requestOperator()
self.timeWaitForOperatorStarted = now()
self.timeWaitForOperatorStarted = self.env.now
# wait until the Broker has waited times equal to loadTime (if any)
yield waitevent, self, self.brokerIsSet
self.timeWaitForOperatorEnded = now()
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
self.timeWaitForOperatorEnded = self.env.now
self.operatorWaitTimeCurrentEntity += self.timeWaitForOperatorEnded-self.timeWaitForOperatorStarted
# variables dedicated to hold the processing times, the time when the Entity entered,
......@@ -324,10 +339,10 @@ class Machine(CoreObject):
# ======= setup the machine if the Setup is defined as one of the Operators' operation types
# in plantSim the setup is performed when the machine has to process a new type of Entity and only once
if any(type=="Setup" for type in self.multOperationTypeList) and self.isOperated():
self.timeSetupStarted = now()
yield hold,self,self.calculateSetupTime()
self.timeSetupStarted = self.env.now
yield self.env.timeout(self.calculateSetupTime())
# TODO: if self.interrupted(): There is the issue of failure during the setup
self.timeSetupEnded = now()
self.timeSetupEnded = self.env.now
self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted
self.totalSetupTime += self.setupTimeCurrentEntity
......@@ -336,10 +351,10 @@ class Machine(CoreObject):
# but setupTime is given for the entity to be processed
# try:
# if self.setupTime and not any(type=="Setup" for type in self.multOperationTypeList):
# self.timeSetupStarted = now()
# self.timeSetupStarted = self.env.now
# yield hold,self,self.calculateSetupTime()
# # TODO: if self.interrupted(): There is the issue of failure during the setup
# self.timeSetupEnded = now()
# self.timeSetupEnded = self.env.now
# self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted
# self.totalSetupTime += self.setupTimeCurrentEntity
# except:
......@@ -355,7 +370,8 @@ class Machine(CoreObject):
# machine has to release the operator
self.releaseOperator()
# wait until the Broker has finished processing
yield waitevent, self, self.brokerIsSet
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# variables used to flag any interruptions and the end of the processing
self.interruption=False
......@@ -368,13 +384,15 @@ class Machine(CoreObject):
while processingNotFinished:
# timeRestartingProcessing : dummy variable to keep track of the time that the processing starts after
# every interruption
self.timeRestartingProcessing=now()
self.timeRestartingProcessing=self.env.now
# wait for the processing time left tinM, if no interruption occurs then change the processingEndedFlag and exit loop,
# else (if interrupted()) set interruption flag to true (only if tinM==0),
# and recalculate the processing time left tinM, passivate while waiting for repair.
# if a preemption has occurred then react accordingly (proceed with getting the critical entity)
yield hold,self, self.tinM # getting processed for remaining processing time tinM
if self.interrupted(): # if a failure occurs while processing the machine is interrupted.
receivedEvent=yield self.env.timeout(self.tinM) | self.interruptionStart # getting processed for remaining processing time tinM
if self.interruptionStart in receivedEvent: # if a failure occurs while processing the machine is interrupted.
assert self.interruptionStart.value==self.env.now, 'the interruption has not been processed on the time of activation'
self.interruptionStart=self.env.event()
self.interruptionActions() # execute interruption actions
# =============== release the operator if there is interruption
......@@ -382,12 +400,14 @@ class Machine(CoreObject):
and self.isOperated()\
and any(type=="Processing" for type in self.multOperationTypeList):
self.releaseOperator()
yield waitevent,self,self.brokerIsSet
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# if there is a failure in the machine or interruption due to preemption, it is passivated
# passivate the Machine for as long as there is no repair
yield waitevent, self, self.interruptionEnd
assert now()==self.interruptionEnd.signalparam, 'the victim of the failure is not the object that received it'
yield self.interruptionEnd
assert self.env.now==self.interruptionEnd.value, 'the victim of the failure is not the object that received it'
self.interruptionEnd=self.env.event()
self.postInterruptionActions()
......@@ -395,10 +415,11 @@ class Machine(CoreObject):
if (self.operatorPool!="None")\
and any(type=="Processing" for type in self.multOperationTypeList)\
and not self.interruption:
self.timeWaitForOperatorStarted = now()
self.timeWaitForOperatorStarted = self.env.now
self.requestOperator()
yield waitevent,self,self.brokerIsSet
self.timeWaitForOperatorEnded = now()
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
self.timeWaitForOperatorEnded = self.env.now
self.operatorWaitTimeCurrentEntity += self.timeWaitForOperatorEnded-self.timeWaitForOperatorStarted
# if the station is reactivated by the preempt method
elif(self.shouldPreempt):
......@@ -409,7 +430,8 @@ class Machine(CoreObject):
and self.isOperated()\
and any(type=="Processing" for type in self.multOperationTypeList):
self.releaseOperator()
yield waitevent,self,self.brokerIsSet
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
self.postInterruptionActions()
break
......@@ -426,30 +448,29 @@ class Machine(CoreObject):
and any(type=="Processing" for type in self.multOperationTypeList)\
and not self.interruption:
self.releaseOperator()
yield waitevent,self,self.brokerIsSet
yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# signal the receiver that the activeObject has something to dispose of
if not self.signalReceiver():
# if there was no available receiver, get into blocking control
while 1:
# wait the event canDispose, this means that the station can deliver the item to successor
event=yield waitevent, self, [self.canDispose, self.interruptionStart]
receivedEvent=yield self.canDispose | self.interruptionStart
# if there was interruption
#if self.interrupted():
# TODO not good implementation
if self.interruptionStart.signalparam==now():
if self.interruptionStart in receivedEvent:
assert self.interruptionStart.value==self.env.now, 'the interruption has not been processed on the time of activation'
self.interruptionStart=self.env.event()
# wait for the end of the interruption
self.interruptionActions() # execute interruption actions
yield waitevent, self, self.interruptionEnd # interruptionEnd to be triggered by ObjectInterruption
assert now()==self.interruptionEnd.signalparam, 'the victim of the failure is not the object that received it'
yield self.interruptionEnd # interruptionEnd to be triggered by ObjectInterruption
assert self.env.now==self.interruptionEnd.value, 'the victim of the failure is not the object that received it'
self.interruptionEnd=self.env.event()
self.postInterruptionActions()
#=======================================================
# TODO: not sure if this is required now
# #if during the interruption the object became empty break
# if (len(self.getActiveObjectQueue())==0 and self.shouldPreempt):
# self.shouldPreempt==False
# break
#=======================================================
if self.canDispose in receivedEvent:
self.canDispose=self.env.event()
# try to signal a receiver, if successful then proceed to get an other entity
if self.signalReceiver():
break
......@@ -458,7 +479,7 @@ class Machine(CoreObject):
# signals the preceding station (e.g. self.machine) and immediately after that gets the entity.
# the preceding machine gets the canDispose signal which is actually useless, is emptied by the following station
# and then cannot exit an infinite loop.
yield hold, self, 0
yield self.env.timeout(0)
# if while waiting (for a canDispose event) became free as the machines that follows emptied it, then proceed
if not self.haveToDispose():
break
......@@ -467,7 +488,7 @@ class Machine(CoreObject):
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def endProcessingActions(self):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
activeEntity=activeObjectQueue[0]
# self.printTrace(activeObject.getActiveObjectQueue()[0].name, processEnd=activeObject.objName)
# reset the variables used to handle the interruptions timing
......@@ -498,16 +519,16 @@ class Machine(CoreObject):
self.waitToDispose=True
#do this so that if it is overtime working it is not counted as off-shift time
if not self.onShift:
self.timeLastShiftEnded=now()
self.timeLastShiftEnded=self.env.now
# update the total working time
# the total processing time for this entity is what the distribution initially gave
if not self.shouldPreempt:
self.totalWorkingTime+=self.totalProcessingTimeInCurrentEntity
# if the station was preemptied for a critical order then calculate the total working time accorindingly
else:
self.totalWorkingTime+=now()-(self.timeLastEntityEntered)
self.totalWorkingTime+=self.env.now-(self.timeLastEntityEntered)
# update the variables keeping track of Entity related attributes of the machine
self.timeLastEntityEnded=now() # this holds the time that the last entity ended processing in Machine
self.timeLastEntityEnded=self.env.now # this holds the time that the last entity ended processing in Machine
self.nameLastEntityEnded=self.currentEntity.name # this holds the name of the last entity that ended processing in Machine
self.completedJobs+=1 # Machine completed one more Job
# reseting the shouldPreempt flag
......@@ -517,7 +538,7 @@ class Machine(CoreObject):
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def interruptionActions(self):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
activeEntity=activeObjectQueue[0]
# self.printTrace(activeEntity.name, interrupted=self.objName)
# if the interrupt occured while processing an entity
......@@ -528,40 +549,40 @@ class Machine(CoreObject):
except IndexError:
pass
# recalculate the processing time left tinM
self.tinM=self.tinM-(now()-self.timeRestartingProcessing)
self.tinM=self.tinM-(self.env.now-self.timeRestartingProcessing)
if(self.tinM==0): # sometimes the failure may happen exactly at the time that the processing would finish
# this may produce disagreement with the simul8 because in both SimPy and Simul8
# it seems to be random which happens 1st
# this should not appear often to stochastic models though where times are random
self.interruption=True
# start counting the down time at breatTime dummy variable
self.breakTime=now() # dummy variable that the interruption happened
self.breakTime=self.env.now # dummy variable that the interruption happened
# =======================================================================
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def postInterruptionActions(self):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
activeEntity=activeObjectQueue[0]
# if the machine returns from an failure while processing an entity
if not self.waitToDispose:
# use the timers to count the time that Machine is down and related
self.downTimeProcessingCurrentEntity+=now()-self.breakTime # count the time that Machine is down while processing this Entity
self.downTimeInCurrentEntity+=now()-self.breakTime # count the time that Machine is down while on currentEntity
self.timeLastFailureEnded=now() # set the timeLastFailureEnded
self.failureTimeInCurrentEntity+=now()-self.breakTime # dummy variable keeping track of the failure time
self.downTimeProcessingCurrentEntity+=self.env.now-self.breakTime # count the time that Machine is down while processing this Entity
self.downTimeInCurrentEntity+=self.env.now-self.breakTime # count the time that Machine is down while on currentEntity
self.timeLastFailureEnded=self.env.now # set the timeLastFailureEnded
self.failureTimeInCurrentEntity+=self.env.now-self.breakTime # dummy variable keeping track of the failure time
# output to trace that the Machine self.objName was passivated for the current failure time
self.outputTrace(activeObjectQueue[0].name, "passivated in "+self.objName+" for "+str(now()-self.breakTime))
self.outputTrace(activeObjectQueue[0].name, "passivated in "+self.objName+" for "+str(self.env.now-self.breakTime))
# when a machine returns from failure while trying to deliver an entity
else:
# count the failure while on current entity time with failureTime variable
self.failureTimeInCurrentEntity+=now()-self.breakTime
self.failureTimeInCurrentEntity+=self.env.now-self.breakTime
# calculate the time the Machine was down while trying to dispose the current Entity,
# and the total down time while on current Entity
self.downTimeInTryingToReleaseCurrentEntity+=now()-self.breakTime
self.downTimeInCurrentEntity+=now()-self.breakTime # already updated from failures during processing
self.downTimeInTryingToReleaseCurrentEntity+=self.env.now-self.breakTime
self.downTimeInCurrentEntity+=self.env.now-self.breakTime # already updated from failures during processing
# update the timeLastFailureEnded
self.timeLastFailureEnded=now()
self.timeLastFailureEnded=self.env.now
# reset the variable holding the time the failure happened
self.breakTime=0
......@@ -577,7 +598,7 @@ class Machine(CoreObject):
# that will give the entity.
# =======================================================================
def canAccept(self, callerObject=None):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
# if we have only one predecessor just check if there is a place and the machine is up
# this is done to achieve better (cpu) processing time
# then we can also use it as a filter for a yield method
......@@ -615,7 +636,7 @@ class Machine(CoreObject):
# also updates the giver to the one that is to be taken
# =======================================================================
def canAcceptAndIsRequested(self,callerObject=None):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
giverObject=callerObject
assert giverObject, 'there must be a caller for canAcceptAndIsRequested'
# check if there is a place, the machine is up and the predecessor has an entity to dispose. if the machine has to compete
......@@ -701,7 +722,7 @@ class Machine(CoreObject):
# checks if the Machine can dispose an entity to the following object
# =======================================================================
def haveToDispose(self, callerObject=None):
activeObjectQueue=self.Res.activeQ
activeObjectQueue=self.Res.users
#if we have only one successor just check if machine waits to dispose and also is up
# this is done to achieve better (cpu) processing time
if(len(self.next)==1 or callerObject==None):
......@@ -796,7 +817,7 @@ class Machine(CoreObject):
offShiftTimeInCurrentEntity=0
if self.interruptCause:
if self.onShift==False and self.interruptCause.type=='ShiftScheduler':
offShiftTimeInCurrentEntity=now()-activeObject.timeLastShiftEnded
offShiftTimeInCurrentEntity=self.env.now-activeObject.timeLastShiftEnded
# if there is an entity that finished processing in a Machine but did not get to reach
# the following Object till the end of simulation,
......@@ -805,9 +826,9 @@ class Machine(CoreObject):
if (len(activeObjectQueue)>0) and (mightBeBlocked)\
and ((activeObject.nameLastEntityEntered == activeObject.nameLastEntityEnded)) and self.onShift:
# be careful here, might have to reconsider
activeObject.totalBlockageTime+=now()-(activeObject.timeLastEntityEnded+activeObject.downTimeInTryingToReleaseCurrentEntity)
activeObject.totalBlockageTime+=self.env.now-(activeObject.timeLastEntityEnded+activeObject.downTimeInTryingToReleaseCurrentEntity)
if activeObject.Up==False:
activeObject.totalBlockageTime-=now()-activeObject.timeLastFailure
activeObject.totalBlockageTime-=self.env.now-activeObject.timeLastFailure
alreadyAdded=True
#if Machine is currently processing an entity we should count this working time
......@@ -817,8 +838,8 @@ class Machine(CoreObject):
#if Machine is down we should add this last failure time to the time that it has been down in current entity
if self.Up==False:
# if(len(activeObjectQueue)>0) and (self.Up==False):
activeObject.downTimeProcessingCurrentEntity+=now()-activeObject.timeLastFailure
activeObject.totalWorkingTime+=now()-activeObject.timeLastEntityEntered\
activeObject.downTimeProcessingCurrentEntity+=self.env.now-activeObject.timeLastFailure
activeObject.totalWorkingTime+=self.env.now-activeObject.timeLastEntityEntered\
-activeObject.downTimeProcessingCurrentEntity\
-activeObject.operatorWaitTimeCurrentEntity\
-activeObject.setupTimeCurrentEntity\
......@@ -830,17 +851,17 @@ class Machine(CoreObject):
and (activeObject.currentOperator==None):
# TODO: needs further research as the time of failure while waiting for operator is not counted yet
if self.Up==False:
activeObject.downTimeProcessingCurrentEntity+=now()-activeObject.timeLastFailure
activeObject.totalTimeWaitingForOperator+=now()-activeObject.timeWaitForOperatorStarted\
activeObject.downTimeProcessingCurrentEntity+=self.env.now-activeObject.timeLastFailure
activeObject.totalTimeWaitingForOperator+=self.env.now-activeObject.timeWaitForOperatorStarted\
-activeObject.downTimeProcessingCurrentEntity\
-offShiftTimeInCurrentEntity
# if Machine is down we have to add this failure time to its total failure time
# we also need to add the last blocking time to total blockage time
if(activeObject.Up==False):
activeObject.totalFailureTime+=now()-activeObject.timeLastFailure
activeObject.totalFailureTime+=self.env.now-activeObject.timeLastFailure
# we add the value only if it hasn't already been added
if((mightBeBlocked) and (activeObject.nameLastEntityEnded==activeObject.nameLastEntityEntered) and (not alreadyAdded)):
activeObject.totalBlockageTime+=(now()-activeObject.timeLastEntityEnded)-(now()-activeObject.timeLastFailure)-activeObject.downTimeInTryingToReleaseCurrentEntity
activeObject.totalBlockageTime+=(self.env.now-activeObject.timeLastEntityEnded)-(self.env.now-activeObject.timeLastFailure)-activeObject.downTimeInTryingToReleaseCurrentEntity
alreadyAdded=True
#if the machine is off shift,add this to the off-shift time
......@@ -849,12 +870,12 @@ class Machine(CoreObject):
#add the time only if the object is interrupted because of off-shift
if self.interruptCause:
if self.interruptCause.type=='ShiftScheduler':
self.totalOffShiftTime+=now()-self.timeLastShiftEnded
self.totalOffShiftTime+=self.env.now-self.timeLastShiftEnded
elif len(self.getActiveObjectQueue())==0 or self.waitToDispose:
self.totalOffShiftTime+=now()-self.timeLastShiftEnded
self.totalOffShiftTime+=self.env.now-self.timeLastShiftEnded
# we add the value only if it hasn't already been added
if((mightBeBlocked) and (activeObject.nameLastEntityEnded==activeObject.nameLastEntityEntered) and (not alreadyAdded)):
activeObject.totalBlockageTime+=(now()-activeObject.timeLastEntityEnded)-(now()-activeObject.timeLastShiftEnded)-offShiftTimeInCurrentEntity
activeObject.totalBlockageTime+=(self.env.now-activeObject.timeLastEntityEnded)-(self.env.now-activeObject.timeLastShiftEnded)-offShiftTimeInCurrentEntity
#Machine was idle when it was not in any other state
activeObject.totalWaitingTime=MaxSimtime-activeObject.totalWorkingTime-activeObject.totalBlockageTime-activeObject.totalFailureTime-activeObject.totalLoadTime-activeObject.totalSetupTime-self.totalOffShiftTime
......
......@@ -26,7 +26,8 @@ Created on 8 Nov 2012
models the source object that generates the entities
'''
from SimPy.Simulation import now, Process, Resource, infinity, hold, SimEvent, activate, waitevent
# from SimPy.Simulation import now, Process, Resource, infinity, hold, SimEvent, activate, waitevent
import simpy
from RandomNumberGenerator import RandomNumberGenerator
from CoreObject import CoreObject
from Globals import G
......@@ -36,20 +37,20 @@ import Globals
#============================================================================
# the EntityGenerator object
#============================================================================
class EntityGenerator(Process):
class EntityGenerator(object):
#===========================================================================
# the __init__ method of the EntityGenerator
#===========================================================================
def __init__(self, victim=None):
Process.__init__(self)
self.env=G.env
self.type="EntityGenerator" #String that shows the type of object
self.victim=victim
#===========================================================================
# initialize method of the EntityGenerator
#===========================================================================
def initialize(self):
Process.__init__(self)
# #===========================================================================
# # initialize method of the EntityGenerator
# #===========================================================================
# def initialize(self):
# Process.__init__(self)
#===========================================================================
# the generator of the EntitiesGenerator
......@@ -59,8 +60,8 @@ class EntityGenerator(Process):
# if the Source is empty create the Entity
if len(self.victim.getActiveObjectQueue())==0:
entity=self.victim.createEntity() # create the Entity object and assign its name
entity.creationTime=now() # assign the current simulation time as the Entity's creation time
entity.startTime=now() # assign the current simulation time as the Entity's start time
entity.creationTime=self.env.now # assign the current simulation time as the Entity's creation time
entity.startTime=self.env.now # assign the current simulation time as the Entity's start time
entity.currentStation=self.victim # update the current station of the Entity
G.EntityList.append(entity)
self.victim.outputTrace(entity.name, "generated") # output the trace
......@@ -68,13 +69,13 @@ class EntityGenerator(Process):
self.victim.numberOfArrivals+=1 # we have one new arrival
G.numberOfEntities+=1
self.victim.appendEntity(entity)
self.victim.entityCreated.signal(entity)
self.victim.entityCreated.succeed(entity)
# else put it on the time list for scheduled Entities
else:
#print now(), 'appending to the list'
self.victim.scheduledEntities.append(now())
#print self.env.now, 'appending to the list'
self.victim.scheduledEntities.append(self.env.now)
self.victim.outputTrace(entity.name, "generated") # output the trace
yield hold,self,self.victim.calculateInterarrivalTime() # wait until the next arrival
yield self.env.timeout(self.victim.calculateInterarrivalTime()) # wait until the next arrival
#============================================================================
# The Source object is a Process
......@@ -104,9 +105,11 @@ class Source(CoreObject):
self.entityGenerator=EntityGenerator(victim=self) # the EntityGenerator of the Source
self.entityCreated=SimEvent('an entity is created')
# self.entityCreated=SimEvent('an entity is created')
self.entityCreated=self.env.event()
# event used by router
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
self.scheduledEntities=[] # list of creations that are scheduled
......@@ -118,15 +121,19 @@ class Source(CoreObject):
CoreObject.initialize(self)
# initialize the internal Queue (type Resource) of the Source
self.Res=Resource(capacity=infinity)
self.Res.activeQ=[]
self.Res.waitQ=[]
# self.Res=Resource(capacity=infinity)
self.Res=simpy.Resource(self.env, capacity=10000)
self.Res.users=[]
# self.Res.waitQ=[]
self.numberOfArrivals = 0
self.entityGenerator.initialize()
activate(self.entityGenerator,self.entityGenerator.run())
self.entityCreated=SimEvent('an entity is created')
# self.entityGenerator.initialize()
# activate(self.entityGenerator,self.entityGenerator.run())
self.env.process(self.entityGenerator.run())
# self.entityCreated=SimEvent('an entity is created')
self.entityCreated=self.env.event()
# event used by router
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
self.scheduledEntities=[] # list of creations that are scheduled
#===========================================================================
......@@ -138,16 +145,18 @@ class Source(CoreObject):
activeObjectQueue=self.getActiveObjectQueue()
while 1:
# wait for any event (entity creation or request for disposal of entity)
yield waitevent, self, [self.entityCreated, self.canDispose, self.loadOperatorAvailable]
receivedEvent=yield self.entityCreated | self.canDispose | self.loadOperatorAvailable
# if an entity is created try to signal the receiver and continue
if self.entityCreated.signalparam:
self.entityCreated.signalparam=None
if self.entityCreated in receivedEvent:
self.entityCreated=self.env.event()
if self.signalReceiver():
continue
# otherwise, if the receiver requests availability then try to signal him if there is anything to dispose of
if self.canDispose.signalparam or self.loadOperatorAvailable.signalparam:
self.canDispose.signalparam=None
self.loadOperatorAvailable.signalparam=None
if self.canDispose in receivedEvent or self.loadOperatorAvailable in receivedEvent:
# self.canDispose.signalparam=None
self.canDispose=self.env.event()
# self.loadOperatorAvailable.signalparam=None
self.loadOperatorAvailable=self.env.event()
if self.haveToDispose():
if self.signalReceiver():
continue
......@@ -188,7 +197,7 @@ class Source(CoreObject):
newEntity=self.createEntity() # create the Entity object and assign its name
newEntity.creationTime=self.scheduledEntities.pop(0) # assign the current simulation time as the Entity's creation time
newEntity.startTime=newEntity.creationTime # assign the current simulation time as the Entity's start time
#print now(), 'getting from the list. StartTime=',newEntity.startTime
#print self.env.now, 'getting from the list. StartTime=',newEntity.startTime
newEntity.currentStation=self # update the current station of the Entity
G.EntityList.append(newEntity)
self.getActiveObjectQueue().append(newEntity) # append the entity to the resource
......@@ -197,5 +206,5 @@ class Source(CoreObject):
self.appendEntity(newEntity)
activeEntity=CoreObject.removeEntity(self, entity) # run the default method
if len(self.getActiveObjectQueue())==1:
self.entityCreated.signal(newEntity)
self.entityCreated.succeed(newEntity)
return activeEntity
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment