sampieters 11 місяців тому
батько
коміт
4258448408
100 змінених файлів з 52237 додано та 271 видалено
  1. 0 2
      README.md
  2. 2 0
      TraceVerifier/TraceChecker.py
  3. 22 22
      examples/BouncingBalls/PyDEVS/target.py
  4. 8897 0
      examples/BouncingBalls/PyDEVS/trace.txt
  5. 0 3
      examples/BouncingBalls/Python/runner.py
  6. 42962 0
      examples/BouncingBalls/Python/trace.txt
  7. 7 7
      examples/BouncingBallsCollision/PyDEVS/target.py
  8. 175 132
      examples/ElevatorBalls/PyDEVS/target.py
  9. 43 20
      examples/ElevatorBalls/Python/target.py
  10. 37 13
      examples/ElevatorBalls/sccd.xml
  11. 3 3
      examples/TimerEventloop/PyDEVS/target.py
  12. 13 7
      sccd/compiler/DEVS_generator.py
  13. 5 13
      sccd/runtime/DEVS_statecharts_core.py
  14. 0 2
      sccd/runtime/statecharts_core.py
  15. 0 0
      tests/1.1) EventlessTransitionTest/config.json
  16. 0 0
      tests/1.1) EventlessTransitionTest/expected_trace.txt
  17. 0 0
      tests/1.1) EventlessTransitionTest/sccd.xml
  18. 2 3
      tests/1.12) NonDeterminismTest/expected_trace.txt
  19. 1 4
      tests/1.12) NonDeterminismTest/sccd.xml
  20. 0 0
      tests/1.13) NonDeterminismHierarchyTest/config.json
  21. 4 0
      tests/1.13) NonDeterminismHierarchyTest/expected_trace.txt
  22. 21 0
      tests/1.13) NonDeterminismHierarchyTest/sccd.xml
  23. 0 0
      tests/1.2) AfterTransitionTest/config.json
  24. 0 0
      tests/1.2) AfterTransitionTest/expected_trace.txt
  25. 0 0
      tests/1.2) AfterTransitionTest/sccd.xml
  26. 0 0
      tests/1.3) GuardConditionTest/config.json
  27. 0 0
      tests/1.3) GuardConditionTest/expected_trace.txt
  28. 1 2
      tests/1.2) GuardConditionTest/sccd.xml
  29. 0 0
      tests/1.4) TransitionToItselfTest/config.json
  30. 0 0
      tests/1.4) TransitionToItselfTest/expected_trace.txt
  31. 2 2
      tests/1.3) TransitionToItselfTest/sccd.xml
  32. 0 0
      tests/1.5) ScriptTransitionTest/config.json
  33. 0 0
      tests/1.5) ScriptTransitionTest/expected_trace.txt
  34. 0 0
      tests/1.5) ScriptTransitionTest/sccd.xml
  35. 0 0
      tests/1.6) ScriptEntryTest/config.json
  36. 0 0
      tests/1.6) ScriptEntryTest/expected_trace.txt
  37. 0 0
      tests/1.6) ScriptEntryTest/sccd.xml
  38. 0 0
      tests/1.7) ScriptExitTest/config.json
  39. 0 0
      tests/1.7) ScriptExitTest/expected_trace.txt
  40. 0 0
      tests/1.7) ScriptExitTest/sccd.xml
  41. 0 0
      tests/1.8) CompositeStateTest/config.json
  42. 0 0
      tests/1.8) CompositeStateTest/expected_trace.txt
  43. 1 2
      tests/1.7) CompositeInitialStateTest/sccd.xml
  44. 0 0
      tests/10.1) TrafficLightTest/config.json
  45. 0 0
      tests/10.1) TrafficLightTest/expected_trace.txt
  46. 0 0
      tests/10.1) TrafficLightTest/input.txt
  47. 0 0
      tests/10.1) TrafficLightTest/sccd.xml
  48. 0 0
      tests/10.2) TrafficLightHistory/config.json
  49. 0 0
      tests/10.2) TrafficLightHistory/expected_trace.txt
  50. 0 0
      tests/10.2) TrafficLightHistory/input.txt
  51. 0 0
      tests/10.2) TrafficLightHistory/sccd.xml
  52. 0 0
      tests/10.3) SimpleBouncingBallsTest/config.json
  53. 0 0
      tests/10.3) SimpleBouncingBallsTest/expected_trace.txt
  54. 0 0
      tests/10.3) SimpleBouncingBallsTest/input.txt
  55. 0 0
      tests/10.3) SimpleBouncingBallsTest/sccd.xml
  56. 0 0
      tests/10.4) OneBallBouncingBallsTest/config.json
  57. 0 0
      tests/10.4) OneBallBouncingBallsTest/expected_trace.txt
  58. 0 0
      tests/10.4) OneBallBouncingBallsTest/input.txt
  59. 0 0
      tests/10.4) OneBallBouncingBallsTest/sccd.xml
  60. 0 0
      tests/10.5) CreateExtraFieldBouncingBallsTest/config.json
  61. 0 0
      tests/10.5) CreateExtraFieldBouncingBallsTest/expected_trace.txt
  62. 0 0
      tests/10.5) CreateExtraFieldBouncingBallsTest/input.txt
  63. 0 0
      tests/10.5) CreateExtraFieldBouncingBallsTest/sccd.xml
  64. 0 0
      tests/2.1) GlobalInputTest/config.json
  65. 0 0
      tests/2.1) GlobalInputTest/expected_trace.txt
  66. 0 0
      tests/2.1) GlobalInputTest/input.txt
  67. 1 1
      tests/2.0) GlobalInputTest/sccd.xml
  68. 0 0
      tests/2.2) GlobalInputCheckTest/config.json
  69. 0 0
      tests/2.2) GlobalInputCheckTest/expected_trace.txt
  70. 0 0
      tests/2.2) GlobalInputCheckTest/input.txt
  71. 0 0
      tests/2.2) GlobalInputCheckTest/sccd.xml
  72. 0 0
      tests/2.3) GlobalInputParameterTest/config.json
  73. 0 0
      tests/2.3) GlobalInputParameterTest/expected_trace.txt
  74. 0 0
      tests/2.3) GlobalInputParameterTest/input.txt
  75. 1 1
      tests/2.2) GlobalInputParameterTest/sccd.xml
  76. 0 0
      tests/2.4) GlobalOutputTest/expected_trace.txt
  77. 0 0
      tests/2.4) GlobalOutputTest/sccd.xml
  78. 0 1
      tests/2.4) GlobalTimedOutputTest/expected_trace.txt
  79. 0 17
      tests/2.4) GlobalTimedOutputTest/sccd.xml
  80. 1 1
      tests/2.5) GlobalTimedOutputTest/expected_trace.txt
  81. 5 7
      tests/2.5) GlobalTimedOutputTest/sccd.xml
  82. 1 0
      tests/2.6) GlobalTimedOutputTest/expected_trace.txt
  83. 19 0
      tests/2.6) GlobalTimedOutputTest/sccd.xml
  84. 0 0
      tests/2.7) GlobalIOTest/expected_trace.txt
  85. 0 0
      tests/2.7) GlobalIOTest/input.txt
  86. 1 1
      tests/2.6) GlobalIOTest/sccd.xml
  87. 0 0
      tests/2.8) MultipleInstancesGlobalInputTest/config.json
  88. 0 0
      tests/2.8) MultipleInstancesGlobalInputTest/expected_trace.txt
  89. 0 0
      tests/2.8) MultipleInstancesGlobalInputTest/input.txt
  90. 1 1
      tests/2.7) MultipleInstanceGlobalInputTest/sccd.xml
  91. 0 0
      tests/2.9) MultipleOutputTest/expected_trace.txt
  92. 0 0
      tests/2.9) MultipleOutputTest/sccd.xml
  93. 0 1
      tests/3.0) ClassCreation/expected_trace.txt
  94. 3 0
      tests/3.1) ClassCreation/config.json
  95. 6 0
      tests/3.1) ClassCreation/expected_trace.txt
  96. 0 0
      tests/3.1) ClassCreation/sccd.xml
  97. 0 3
      tests/3.1) ClassInitialisation/expected_trace.txt
  98. 0 0
      tests/3.10) DeleteBadFromNonParent/expected_trace.txt
  99. 0 0
      tests/3.10) DeleteBadFromNonParent/sccd.xml
  100. 0 0
      tests/3.10) DeleteGoodFromNonParent/expected_trace.txt

+ 0 - 2
README.md

@@ -201,7 +201,5 @@ A window can also be deleted by clicking on the close window button on the top r
 
 ## TODO
 - [] Create elevator balls example
-- [] Fix bug in narrow cast for testing framework
-- maybe add private ports tests
 - [] Check paper
 - [] Send in paper, FINALLY!

+ 2 - 0
TraceVerifier/TraceChecker.py

@@ -245,6 +245,8 @@ class PythonSCCDTraceChecker(SCCDTraceChecker):
             "extra_info": None
         }
         
+        # Clean id dictionary for following test
+        self.id_dict = {}
         with open(log, 'r') as file:
             lines = file.readlines()
             

+ 22 - 22
examples/BouncingBalls/PyDEVS/target.py

@@ -15,9 +15,9 @@ CANVAS_DIMS = (800, 550)
 
 # package "Bouncing_Balls_DEVS_Version"
 
-class MainAppInstance(RuntimeClassBase):
+class MainAppInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -193,11 +193,11 @@ class MainAppInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/running"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class MainApp(ClassBase):
+class MainApp(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
         new_instance = self.constructObject(0, 0, [])
@@ -209,9 +209,9 @@ class MainApp(ClassBase):
         new_instance = MainAppInstance(self, id, start_port_id)
         return new_instance
 
-class FieldInstance(RuntimeClassBase):
+class FieldInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -464,11 +464,11 @@ class FieldInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/root"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class Field(ClassBase):
+class Field(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
         self.field_ui = self.addInPort("field_ui")
@@ -477,9 +477,9 @@ class Field(ClassBase):
         new_instance = FieldInstance(self, id, start_port_id)
         return new_instance
 
-class ButtonInstance(RuntimeClassBase):
+class ButtonInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id, window_id, event_name, button_text):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -568,11 +568,11 @@ class ButtonInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/creating_button"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class Button(ClassBase):
+class Button(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
         self.button_ui = self.addInPort("button_ui")
@@ -581,9 +581,9 @@ class Button(ClassBase):
         new_instance = ButtonInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3])
         return new_instance
 
-class BallInstance(RuntimeClassBase):
+class BallInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id, canvas_id, x, y):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -791,11 +791,11 @@ class BallInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/main_behaviour"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class Ball(ClassBase):
+class Ball(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
         self.ball_ui = self.addInPort("ball_ui")
@@ -804,7 +804,7 @@ class Ball(ClassBase):
         new_instance = BallInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3])
         return new_instance
 
-def instantiate(self, class_name, construct_params):
+def instantiate(self, class_name):
     instance = {}
     instance["name"] = class_name
     if class_name == "MainApp":
@@ -839,7 +839,7 @@ class ObjectManager(ObjectManagerBase):
         self.output["Field"] = self.addOutPort()
         self.output["Button"] = self.addOutPort()
         self.output["Ball"] = self.addOutPort()
-        self.state.createInstance("MainApp", [])
+        self.state.createInstance("MainApp")
 
 class Controller(CoupledDEVS):
     def __init__(self, name):

Різницю між файлами не показано, бо вона завелика
+ 8897 - 0
examples/BouncingBalls/PyDEVS/trace.txt


+ 0 - 3
examples/BouncingBalls/Python/runner.py

@@ -28,8 +28,5 @@ if __name__ == '__main__':
 
 	controller.setVerbose("./examples/BouncingBalls/Python/trace.txt")
 
-	actual_event = Event("hello", "ui")
-	controller.addInput(actual_event, 500)
-
 	controller.start()
 	tkroot.mainloop()

Різницю між файлами не показано, бо вона завелика
+ 42962 - 0
examples/BouncingBalls/Python/trace.txt


+ 7 - 7
examples/BouncingBallsCollision/PyDEVS/target.py

@@ -32,7 +32,7 @@ class MainAppInstance(RuntimeClassBase):
         # call user defined constructor
         MainAppInstance.user_defined_constructor(self)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
     
@@ -230,7 +230,7 @@ class FieldInstance(RuntimeClassBase):
         # call user defined constructor
         FieldInstance.user_defined_constructor(self)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("field_ui", start_port_id + 1)
@@ -586,7 +586,7 @@ class ButtonInstance(RuntimeClassBase):
         # call user defined constructor
         ButtonInstance.user_defined_constructor(self, window_id, event_name, button_text)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("button_ui", start_port_id + 1)
@@ -689,7 +689,7 @@ class BallInstance(RuntimeClassBase):
         # call user defined constructor
         BallInstance.user_defined_constructor(self, canvas_id, x, y)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("ball_ui", start_port_id + 1)
@@ -921,7 +921,7 @@ class CollisionPhysicsInstance(RuntimeClassBase):
         # call user defined constructor
         CollisionPhysicsInstance.user_defined_constructor(self, ball1_id, ball2_id, ball1_info, ball2_info)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("physics_ui", start_port_id + 1)
@@ -1042,7 +1042,7 @@ class CollisionPhysics(ClassBase):
         new_instance = CollisionPhysicsInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3], parameters[4])
         return new_instance
 
-def instantiate(self, class_name, construct_params):
+def instantiate(self, class_name):
     instance = {}
     instance["name"] = class_name
     if class_name == "MainApp":
@@ -1083,7 +1083,7 @@ class ObjectManager(ObjectManagerBase):
         self.output["Button"] = self.addOutPort()
         self.output["Ball"] = self.addOutPort()
         self.output["CollisionPhysics"] = self.addOutPort()
-        self.state.createInstance("MainApp", [])
+        self.state.createInstance("MainApp")
 
 class Controller(CoupledDEVS):
     def __init__(self, name):

+ 175 - 132
examples/ElevatorBalls/PyDEVS/target.py

@@ -18,9 +18,9 @@ FLOORS = 3
 
 # package "Elevator Balls"
 
-class MainAppInstance(RuntimeClassBase):
+class MainAppInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -40,7 +40,7 @@ class MainAppInstance(RuntimeClassBase):
         # call user defined constructor
         MainAppInstance.user_defined_constructor(self)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("field_ui", start_port_id + 1)
@@ -81,27 +81,30 @@ class MainAppInstance(RuntimeClassBase):
         # state /create_floors
         self.states["/create_floors"] = State(5, "/create_floors", self)
         
-        # state /wait
-        self.states["/wait"] = State(6, "/wait", self)
+        # state /wait_created
+        self.states["/wait_created"] = State(6, "/wait_created", self)
+        
+        # state /wait_started
+        self.states["/wait_started"] = State(7, "/wait_started", self)
         
         # state /create_controls
-        self.states["/create_controls"] = State(7, "/create_controls", self)
+        self.states["/create_controls"] = State(8, "/create_controls", self)
         
         # state /create_controls/create_buttons
-        self.states["/create_controls/create_buttons"] = State(8, "/create_controls/create_buttons", self)
+        self.states["/create_controls/create_buttons"] = State(9, "/create_controls/create_buttons", self)
         
         # state /create_controls/create_buttons/create_a_button
-        self.states["/create_controls/create_buttons/create_a_button"] = State(9, "/create_controls/create_buttons/create_a_button", self)
+        self.states["/create_controls/create_buttons/create_a_button"] = State(10, "/create_controls/create_buttons/create_a_button", self)
         self.states["/create_controls/create_buttons/create_a_button"].setEnter(self._create_controls_create_buttons_create_a_button_enter)
         
         # state /create_controls/create_buttons/start_a_button
-        self.states["/create_controls/create_buttons/start_a_button"] = State(10, "/create_controls/create_buttons/start_a_button", self)
+        self.states["/create_controls/create_buttons/start_a_button"] = State(11, "/create_controls/create_buttons/start_a_button", self)
         
         # state /create_controls/create_buttons/check_next
-        self.states["/create_controls/create_buttons/check_next"] = State(11, "/create_controls/create_buttons/check_next", self)
+        self.states["/create_controls/create_buttons/check_next"] = State(12, "/create_controls/create_buttons/check_next", self)
         
         # state /running
-        self.states["/running"] = State(12, "/running", self)
+        self.states["/running"] = State(13, "/running", self)
         
         # add children
         self.states[""].addChild(self.states["/creating_window"])
@@ -109,7 +112,8 @@ class MainAppInstance(RuntimeClassBase):
         self.states[""].addChild(self.states["/create_elevator"])
         self.states[""].addChild(self.states["/creating"])
         self.states[""].addChild(self.states["/create_floors"])
-        self.states[""].addChild(self.states["/wait"])
+        self.states[""].addChild(self.states["/wait_created"])
+        self.states[""].addChild(self.states["/wait_started"])
         self.states[""].addChild(self.states["/create_controls"])
         self.states[""].addChild(self.states["/running"])
         self.states["/create_controls"].addChild(self.states["/create_controls/create_buttons"])
@@ -146,24 +150,26 @@ class MainAppInstance(RuntimeClassBase):
         self.states["/creating"].addTransition(_creating_0)
         
         # transition /create_floors
-        _create_floors_0 = Transition(self, self.states["/create_floors"], [self.states["/create_controls"]])
+        _create_floors_0 = Transition(self, self.states["/create_floors"], [self.states["/wait_created"]])
+        _create_floors_0.setAction(self._create_floors_0_exec)
         _create_floors_0.setTrigger(None)
-        _create_floors_0.setGuard(self._create_floors_0_guard)
         self.states["/create_floors"].addTransition(_create_floors_0)
-        _create_floors_1 = Transition(self, self.states["/create_floors"], [self.states["/wait"]])
-        _create_floors_1.setAction(self._create_floors_1_exec)
-        _create_floors_1.setTrigger(None)
-        _create_floors_1.setGuard(self._create_floors_1_guard)
-        self.states["/create_floors"].addTransition(_create_floors_1)
-        
-        # transition /wait
-        _wait_0 = Transition(self, self.states["/wait"], [self.states["/wait"]])
-        _wait_0.setAction(self._wait_0_exec)
-        _wait_0.setTrigger(Event("instance_created", None))
-        self.states["/wait"].addTransition(_wait_0)
-        _wait_1 = Transition(self, self.states["/wait"], [self.states["/create_floors"]])
-        _wait_1.setTrigger(Event("instance_started", None))
-        self.states["/wait"].addTransition(_wait_1)
+        
+        # transition /wait_created
+        _wait_created_0 = Transition(self, self.states["/wait_created"], [self.states["/wait_started"]])
+        _wait_created_0.setAction(self._wait_created_0_exec)
+        _wait_created_0.setTrigger(Event("instance_created", None))
+        self.states["/wait_created"].addTransition(_wait_created_0)
+        
+        # transition /wait_started
+        _wait_started_0 = Transition(self, self.states["/wait_started"], [self.states["/create_floors"]])
+        _wait_started_0.setTrigger(Event("instance_started", None))
+        _wait_started_0.setGuard(self._wait_started_0_guard)
+        self.states["/wait_started"].addTransition(_wait_started_0)
+        _wait_started_1 = Transition(self, self.states["/wait_started"], [self.states["/create_controls"]])
+        _wait_started_1.setTrigger(Event("instance_started", None))
+        _wait_started_1.setGuard(self._wait_started_1_guard)
+        self.states["/wait_started"].addTransition(_wait_started_1)
         
         # transition /create_controls/create_buttons/create_a_button
         _create_controls_create_buttons_create_a_button_0 = Transition(self, self.states["/create_controls/create_buttons/create_a_button"], [self.states["/create_controls/create_buttons/start_a_button"]])
@@ -190,15 +196,8 @@ class MainAppInstance(RuntimeClassBase):
         # transition /running
         _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
         _running_0.setAction(self._running_0_exec)
-        _running_0.setTrigger(Event("update_bounds", None))
+        _running_0.setTrigger(Event("button_pressed", None))
         self.states["/running"].addTransition(_running_0)
-        _running_1 = Transition(self, self.states["/running"], [self.states["/running"]])
-        _running_1.setAction(self._running_1_exec)
-        _running_1.setTrigger(Event("button_pressed", None))
-        self.states["/running"].addTransition(_running_1)
-        _running_2 = Transition(self, self.states["/running"], [self.states["/running"]])
-        _running_2.setTrigger(Event("open_elevator", None))
-        self.states["/running"].addTransition(_running_2)
     
     def _creating_window_enter(self):
         self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [CANVAS_DIMS[0], CANVAS_DIMS[1], "Bouncing Balls Elevator", self.inports['field_ui']]))
@@ -207,7 +206,7 @@ class MainAppInstance(RuntimeClassBase):
         self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_DIMS[0], CANVAS_DIMS[1] - 150, {'background':'#fff'}, self.inports['field_ui']]))
     
     def _create_controls_create_buttons_create_a_button_enter(self):
-        self.big_step.outputEventOM(Event("create_instance", None, [self, "button", "ElevatorButton", self.window_id, self.canvas_id, self.button_num]))
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "button", "ElevatorButton", self.window_id, self.canvas_id, self.button_num -1]))
     
     def _creating_window_0_exec(self, parameters):
         window_id = parameters[0]
@@ -227,19 +226,20 @@ class MainAppInstance(RuntimeClassBase):
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name, self.canvas_id, self.window_id])]))
     
-    def _create_floors_0_guard(self, parameters):
-        return self.num_floors == FLOORS
-    
-    def _create_floors_1_exec(self, parameters):
+    def _create_floors_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("create_instance", None, [self, "floor", "Floor", self.canvas_id, self.num_floors]))
         self.num_floors += 1
     
-    def _create_floors_1_guard(self, parameters):
-        return self.num_floors != FLOORS
-    
-    def _wait_0_exec(self, parameters):
+    def _wait_created_0_exec(self, parameters):
         association_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
+        self.big_step.outputEventOM(Event("associate_instance", None, [self, association_name, 'elevator/floors']))
+    
+    def _wait_started_0_guard(self, parameters):
+        return self.num_floors != FLOORS
+    
+    def _wait_started_1_guard(self, parameters):
+        return self.num_floors == FLOORS
     
     def _create_controls_create_buttons_create_a_button_0_exec(self, parameters):
         association_name = parameters[0]
@@ -249,45 +249,38 @@ class MainAppInstance(RuntimeClassBase):
         self.button_num -= 1
     
     def _create_controls_create_buttons_check_next_0_guard(self, parameters):
-        return self.button_num != 0
+        return self.button_num != 1
     
     def _create_controls_create_buttons_check_next_1_guard(self, parameters):
-        return self.button_num == 0
+        return self.button_num == 1
     
     def _running_0_exec(self, parameters):
-        pos = parameters[0]
-        dim = parameters[1]
-        vel = parameters[2]
-        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("update_elevator_bounds", None, [pos, dim, vel])]))
-    
-    def _running_1_exec(self, parameters):
         floor_number = parameters[0]
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'elevator', Event("move_elevator", None, [floor_number])]))
     
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/creating_window"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class MainApp(ClassBase):
+class MainApp(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
-        self.outputs["floor"] = self.addOutPort("floor")
-        self.outputs["button"] = self.addOutPort("button")
-        self.outputs["elevator"] = self.addOutPort("elevator")
         self.field_ui = self.addInPort("field_ui")
         new_instance = self.constructObject(0, 0, [])
         self.state.instances[new_instance.instance_id] = new_instance
+        new_instance.start()
+        self.state.next_time = 0
     
     def constructObject(self, id, start_port_id, parameters):
         new_instance = MainAppInstance(self, id, start_port_id)
         return new_instance
 
-class FloorInstance(RuntimeClassBase):
+class FloorInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id, canvas_id, floor_num):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -306,7 +299,7 @@ class FloorInstance(RuntimeClassBase):
         # call user defined constructor
         FloorInstance.user_defined_constructor(self, canvas_id, floor_num)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("floor_ui", start_port_id + 1)
@@ -323,6 +316,12 @@ class FloorInstance(RuntimeClassBase):
         
         self.dim = {'x': FLOOR_LENGTH, 'y': y_dim};
         
+        self.elevator_open = False
+        
+        self.elev_pos = None
+        self.elev_dim = None
+        self.elev_vel = None
+        
         
         # start position from the bottom instead of from the top
         # self.pos = {'x': FLOOR_LENGTH / 2, 'y': (y_dim /2) + (self.floor_num * (y_dim + FLOOR_SPACE))};
@@ -373,6 +372,22 @@ class FloorInstance(RuntimeClassBase):
         _running_create_random_ball_0.setAction(self._running_create_random_ball_0_exec)
         _running_create_random_ball_0.setTrigger(Event("_0after"))
         self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_0)
+        _running_create_random_ball_1 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
+        _running_create_random_ball_1.setAction(self._running_create_random_ball_1_exec)
+        _running_create_random_ball_1.setTrigger(Event("open_elevator", None))
+        self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_1)
+        _running_create_random_ball_2 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
+        _running_create_random_ball_2.setAction(self._running_create_random_ball_2_exec)
+        _running_create_random_ball_2.setTrigger(Event("close_elevator", None))
+        self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_2)
+        _running_create_random_ball_3 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
+        _running_create_random_ball_3.setAction(self._running_create_random_ball_3_exec)
+        _running_create_random_ball_3.setTrigger(Event("update_bounds", None))
+        self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_3)
+        _running_create_random_ball_4 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
+        _running_create_random_ball_4.setAction(self._running_create_random_ball_4_exec)
+        _running_create_random_ball_4.setTrigger(Event("transfer_ball", None))
+        self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_4)
         
         # transition /running/wait
         _running_wait_0 = Transition(self, self.states["/running/wait"], [self.states["/running/create_random_ball"]])
@@ -390,7 +405,34 @@ class FloorInstance(RuntimeClassBase):
         self.removeTimer(0)
     
     def _running_create_random_ball_0_exec(self, parameters):
-        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, 10, self.pos['y']]))
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, {'x': 10, 'y': self.pos['y']}, {'x': random.uniform(1.0, 5.0), 'y': random.uniform(-5.0, 5.0)}, self.elevator_open, self.elev_pos, self.elev_dim, self.elev_vel]))
+    
+    def _running_create_random_ball_1_exec(self, parameters):
+        print("Elevator opened at:", self.floor_num)
+        self.elevator_open = True
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'balls', Event("update_elevator_open", None, [self.elevator_open])]))
+    
+    def _running_create_random_ball_2_exec(self, parameters):
+        print("Elevator closed at:", self.floor_num)
+        self.elevator_open = False
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'balls', Event("update_elevator_open", None, [self.elevator_open])]))
+    
+    def _running_create_random_ball_3_exec(self, parameters):
+        elev_pos = parameters[0]
+        elev_dim = parameters[1]
+        elev_vel = parameters[2]
+        self.elev_pos = elev_pos
+        self.elev_dim = elev_dim
+        self.elev_vel = elev_vel
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'balls', Event("update_elevator_bounds", None, [elev_pos, elev_dim, elev_vel])]))
+    
+    def _running_create_random_ball_4_exec(self, parameters):
+        link_id = parameters[0]
+        prev_floor = parameters[1]
+        new_floor = parameters[2]
+        pos = parameters[3]
+        vel = parameters[4]
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, new_floor, pos, {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)}, self.elevator_open, self.elev_pos, self.elev_dim, self.elev_vel]))
     
     def _running_wait_0_exec(self, parameters):
         association_name = parameters[0]
@@ -400,24 +442,22 @@ class FloorInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/creating_floor"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class Floor(ClassBase):
+class Floor(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
-        self.outputs["parent"] = self.addOutPort("parent")
-        self.outputs["balls"] = self.addOutPort("balls")
         self.floor_ui = self.addInPort("floor_ui")
     
     def constructObject(self, id, start_port_id, parameters):
         new_instance = FloorInstance(self, id, start_port_id, parameters[1], parameters[2])
         return new_instance
 
-class ElevatorButtonInstance(RuntimeClassBase):
+class ElevatorButtonInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id, window_id, canvas_id, number):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -431,7 +471,7 @@ class ElevatorButtonInstance(RuntimeClassBase):
         # call user defined constructor
         ElevatorButtonInstance.user_defined_constructor(self, window_id, canvas_id, number)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("button_ui", start_port_id + 1)
@@ -507,23 +547,22 @@ class ElevatorButtonInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/creating"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class ElevatorButton(ClassBase):
+class ElevatorButton(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
-        self.outputs["parent"] = self.addOutPort("parent")
         self.button_ui = self.addInPort("button_ui")
     
     def constructObject(self, id, start_port_id, parameters):
         new_instance = ElevatorButtonInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3])
         return new_instance
 
-class ElevatorInstance(RuntimeClassBase):
+class ElevatorInstance(RuntimeStatechartBase):
     def __init__(self, atomdevs, id, start_port_id, canvas_id):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -542,7 +581,7 @@ class ElevatorInstance(RuntimeClassBase):
         # call user defined constructor
         ElevatorInstance.user_defined_constructor(self, canvas_id)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("elevator_ui", start_port_id + 1)
@@ -635,7 +674,6 @@ class ElevatorInstance(RuntimeClassBase):
         _root_running_move_0.setTrigger(Event("_0after"))
         self.states["/root/running/move"].addTransition(_root_running_move_0)
         _root_running_move_1 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/idle"]])
-        _root_running_move_1.setAction(self._root_running_move_1_exec)
         _root_running_move_1.setTrigger(None)
         _root_running_move_1.setGuard(self._root_running_move_1_guard)
         self.states["/root/running/move"].addTransition(_root_running_move_1)
@@ -644,10 +682,11 @@ class ElevatorInstance(RuntimeClassBase):
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['elevator_ui']]))
     
     def _root_running_idle_enter(self):
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("update_bounds", None, [self.pos, self.dim, self.vel])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'floors', Event("update_bounds", None, [self.pos, self.dim, self.vel])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, f'floors[{self.current_floor}]', Event("open_elevator", None, [])]))
     
     def _root_running_move_enter(self):
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("update_bounds", None, [self.pos, self.dim, self.vel])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'floors', Event("update_bounds", None, [self.pos, self.dim, self.vel])]))
         self.addTimer(0, 0.02)
     
     def _root_running_move_exit(self):
@@ -668,6 +707,7 @@ class ElevatorInstance(RuntimeClassBase):
     
     def _root_running_idle_0_exec(self, parameters):
         floor_number = parameters[0]
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, f'floors[{self.current_floor}]', Event("close_elevator", None, [])]))
         if self.current_floor < floor_number:
             self.vel = -2
         else:
@@ -683,33 +723,28 @@ class ElevatorInstance(RuntimeClassBase):
         self.big_step.outputEvent(Event("set_element_pos", self.getOutPortName("ui"), [self.canvas_id, self.elevator_id, self.pos['x'], self.pos['y']]))
         self.pos['y'] += self.vel
     
-    def _root_running_move_1_exec(self, parameters):
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("open_elevator", None, [])]))
-    
     def _root_running_move_1_guard(self, parameters):
         return (self.vel > 0 and self.pos['y'] > self.next_pos['y']) or (self.vel < 0 and self.pos['y'] < self.next_pos['y'])
     
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/root"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class Elevator(ClassBase):
+class Elevator(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
-        self.outputs["floors"] = self.addOutPort("floors")
-        self.outputs["parent"] = self.addOutPort("parent")
         self.elevator_ui = self.addInPort("elevator_ui")
     
     def constructObject(self, id, start_port_id, parameters):
         new_instance = ElevatorInstance(self, id, start_port_id, parameters[1])
         return new_instance
 
-class BallInstance(RuntimeClassBase):
-    def __init__(self, atomdevs, id, start_port_id, canvas_id, floor_num, x, y):
-        RuntimeClassBase.__init__(self, atomdevs, id)
+class BallInstance(RuntimeStatechartBase):
+    def __init__(self, atomdevs, id, start_port_id, canvas_id, floor_num, pos, vel, elevator_open, rect_pos, rect_dim, rect_vel):
+        RuntimeStatechartBase.__init__(self, atomdevs, id)
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.internal_event_lifeline = StatechartSemantics.Queue
@@ -725,27 +760,31 @@ class BallInstance(RuntimeClassBase):
         self.pos = None
         
         # call user defined constructor
-        BallInstance.user_defined_constructor(self, canvas_id, floor_num, x, y)
+        BallInstance.user_defined_constructor(self, canvas_id, floor_num, pos, vel, elevator_open, rect_pos, rect_dim, rect_vel)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("ball_ui", start_port_id + 1)
         atomdevs.state.port_mappings[port_name] = id
         self.inports["ball_ui"] = port_name
     
-    def user_defined_constructor(self, canvas_id, floor_num, x, y):
+    def user_defined_constructor(self, canvas_id, floor_num, pos, vel, elevator_open, rect_pos, rect_dim, rect_vel):
         self.canvas_id = canvas_id;
         
         
         self.floor_num = floor_num;
         
         self.elevator_floor = 0;
-        self.elevator_open = True;
+        self.elevator_open = elevator_open;
+        
+        self.rect_pos = rect_pos
+        self.rect_dim = rect_dim
+        self.rect_vel = rect_vel
         
         self.r = 5.0;
-        self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
-        self.pos = {'x': x, 'y': y};
+        self.vel = vel;
+        self.pos = pos;
         self.smooth = 0.6; # value between 0 and 1
     
     def user_defined_destructor(self):
@@ -805,11 +844,12 @@ class BallInstance(RuntimeClassBase):
         # transition /main_behaviour/bouncing
         _main_behaviour_bouncing_0 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
         _main_behaviour_bouncing_0.setAction(self._main_behaviour_bouncing_0_exec)
-        _main_behaviour_bouncing_0.setTrigger(Event("_0after"))
+        _main_behaviour_bouncing_0.setTrigger(None)
+        _main_behaviour_bouncing_0.setGuard(self._main_behaviour_bouncing_0_guard)
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_0)
         _main_behaviour_bouncing_1 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
         _main_behaviour_bouncing_1.setAction(self._main_behaviour_bouncing_1_exec)
-        _main_behaviour_bouncing_1.setTrigger(Event("open_elevator", None))
+        _main_behaviour_bouncing_1.setTrigger(Event("_0after"))
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_1)
         _main_behaviour_bouncing_2 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/ball_delete"]])
         _main_behaviour_bouncing_2.setTrigger(None)
@@ -817,8 +857,12 @@ class BallInstance(RuntimeClassBase):
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_2)
         _main_behaviour_bouncing_3 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
         _main_behaviour_bouncing_3.setAction(self._main_behaviour_bouncing_3_exec)
-        _main_behaviour_bouncing_3.setTrigger(Event("update_elevator_bounds", None))
+        _main_behaviour_bouncing_3.setTrigger(Event("update_elevator_open", None))
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_3)
+        _main_behaviour_bouncing_4 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
+        _main_behaviour_bouncing_4.setAction(self._main_behaviour_bouncing_4_exec)
+        _main_behaviour_bouncing_4.setTrigger(Event("update_elevator_bounds", None))
+        self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_4)
         
         # transition /main_behaviour/ball_delete
         _main_behaviour_ball_delete_0 = Transition(self, self.states["/main_behaviour/ball_delete"], [self.states["/deleted"]])
@@ -845,12 +889,24 @@ class BallInstance(RuntimeClassBase):
         self.circle_id = circle_id
     
     def _main_behaviour_bouncing_0_exec(self, parameters):
+        self.prev_floor = self.floor_num
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("transfer_ball", None, [self.association_name, self.prev_floor, self.elevator_floor, self.pos, self.vel])]))
+    
+    def _main_behaviour_bouncing_0_guard(self, parameters):
+        return self.pos['x'] + self.r > self.rect_pos['x'] + (self.rect_dim['x'] / 2) and self.elevator_open
+    
+    def _main_behaviour_bouncing_1_exec(self, parameters):
+        floor_height = ((CANVAS_DIMS[1] - 150) - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
+        floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
+        floor_pos = {'x': FLOOR_LENGTH / 2, 'y': (CANVAS_DIMS[1] - 150) - (floor_height /2) - ( self.floor_num * (floor_height + FLOOR_SPACE)  )};
+        
         if self.floor_num == -1:
-            pass
-            """
             if self.pos['x'] - self.r < self.rect_pos['x'] - (self.rect_dim['x'] / 2):
-                if self.elevator_open:
+                if self.elevator_open and self.vel['x'] < 0:
+                    print("Delivered ball from floor:", self.floor_num, "to:", self.elevator_floor)
                     self.floor_num = self.elevator_floor
+                elif self.vel['x'] >= 0:
+                    pass
                 else:
                     self.pos['x'] = self.rect_pos['x'] - (self.rect_dim['x'] / 2) + self.r
                     self.vel['x'] = -self.vel['x']
@@ -865,18 +921,15 @@ class BallInstance(RuntimeClassBase):
             elif self.pos['y'] + self.r > self.rect_pos['y'] + (self.rect_dim['y'] / 2):
                 self.pos['y'] = self.rect_pos['y'] + (self.rect_dim['y'] / 2) - self.r
                 self.vel['y'] = -self.vel['y'] + self.rect_vel
-            """
         else:
-            floor_height = ((CANVAS_DIMS[1] - 150) - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
-            floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
-            floor_pos = {'x': FLOOR_LENGTH / 2, 'y': (CANVAS_DIMS[1] - 150) - (floor_height /2) - ( self.floor_num * (floor_height + FLOOR_SPACE)  )};
-        
             if self.pos['x'] - self.r < floor_pos['x'] - (floor_dim['x'] / 2):
                 self.pos['x'] = floor_pos['x'] - (floor_dim['x'] / 2) + self.r
                 self.vel['x'] = -self.vel['x']
             elif self.pos['x'] + self.r > floor_pos['x'] + (floor_dim['x'] / 2):
-                if self.elevator_open and (self.elevator_floor == self.floor_num):
+                if self.elevator_open and self.vel['x'] > 0:
                     self.floor_num = -1
+                elif self.vel['x'] <= 0:
+                    pass
                 else:
                     self.pos['x'] = floor_pos['x'] + (floor_dim['x'] / 2) - self.r
                     self.vel['x'] = -self.vel['x']
@@ -892,20 +945,21 @@ class BallInstance(RuntimeClassBase):
         self.pos['x'] += self.vel['x']
         self.pos['y'] += self.vel['y']
     
-    def _main_behaviour_bouncing_1_exec(self, parameters):
-        self.elevator_open = True
-    
     def _main_behaviour_bouncing_2_guard(self, parameters):
         return self.pos['x'] - self.r < 2
     
     def _main_behaviour_bouncing_3_exec(self, parameters):
+        open_bool = parameters[0]
+        self.elevator_open = open_bool
+        print("Ball on floor floor_num:", self.floor_num, "went open")
+    
+    def _main_behaviour_bouncing_4_exec(self, parameters):
         pos = parameters[0]
         dim = parameters[1]
         vel = parameters[2]
         self.rect_pos = pos
         self.rect_dim = dim
         self.rect_vel = vel
-        self.elevator_open = False
     
     def _main_behaviour_ball_delete_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'floor', Event("delete_ball", None, [self.association_name])]))
@@ -914,21 +968,20 @@ class BallInstance(RuntimeClassBase):
     def initializeStatechart(self):
         # enter default state
         self.default_targets = self.states["/main_behaviour"].getEffectiveTargetStates()
-        RuntimeClassBase.initializeStatechart(self)
+        RuntimeStatechartBase.initializeStatechart(self)
 
-class Ball(ClassBase):
+class Ball(RuntimeClassBase):
     def __init__(self, name):
-        ClassBase.__init__(self, name)
+        RuntimeClassBase.__init__(self, name)
         self.input = self.addInPort("input")
         self.glob_outputs["ui"] = self.addOutPort("ui")
-        self.outputs["parent"] = self.addOutPort("parent")
         self.ball_ui = self.addInPort("ball_ui")
     
     def constructObject(self, id, start_port_id, parameters):
-        new_instance = BallInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3], parameters[4])
+        new_instance = BallInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8])
         return new_instance
 
-def instantiate(self, class_name, construct_params):
+def instantiate(self, class_name):
     instance = {}
     instance["name"] = class_name
     if class_name == "MainApp":
@@ -954,7 +1007,7 @@ def instantiate(self, class_name, construct_params):
     elif class_name == "Ball":
         self.narrow_cast_id = self.narrow_cast_id + 1
         instance["associations"] = {}
-        instance["associations"]["parent"] = Association("MainApp", 1, 1)
+        instance["associations"]["parent"] = Association("Floor", 1, 1)
     else:
         raise Exception("Cannot instantiate class " + class_name)
     return instance
@@ -970,8 +1023,7 @@ class ObjectManager(ObjectManagerBase):
         self.output["ElevatorButton"] = self.addOutPort()
         self.output["Elevator"] = self.addOutPort()
         self.output["Ball"] = self.addOutPort()
-        self.state.createInstance("MainApp", [])
-        self.state.to_send.append((("MainApp", 0), ("MainApp", 0), Event("start_instance", None, ["MainApp[0]"])))
+        self.state.createInstance("MainApp")
 
 class Controller(CoupledDEVS):
     def __init__(self, name):
@@ -987,23 +1039,14 @@ class Controller(CoupledDEVS):
         self.atomics.append(self.addSubModel(Ball("Ball")))
         self.connectPorts(self.atomics[0].obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["MainApp"], self.atomics[0].obj_manager_in)
-        self.connectPorts(self.atomics[0].outputs["floor"], self.atomics[1].input)
-        self.connectPorts(self.atomics[0].outputs["button"], self.atomics[2].input)
-        self.connectPorts(self.atomics[0].outputs["elevator"], self.atomics[3].input)
         self.connectPorts(self.atomics[1].obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["Floor"], self.atomics[1].obj_manager_in)
-        self.connectPorts(self.atomics[1].outputs["parent"], self.atomics[0].input)
-        self.connectPorts(self.atomics[1].outputs["balls"], self.atomics[4].input)
         self.connectPorts(self.atomics[2].obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["ElevatorButton"], self.atomics[2].obj_manager_in)
-        self.connectPorts(self.atomics[2].outputs["parent"], self.atomics[0].input)
         self.connectPorts(self.atomics[3].obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["Elevator"], self.atomics[3].obj_manager_in)
-        self.connectPorts(self.atomics[3].outputs["floors"], self.atomics[1].input)
-        self.connectPorts(self.atomics[3].outputs["parent"], self.atomics[0].input)
         self.connectPorts(self.atomics[4].obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["Ball"], self.atomics[4].obj_manager_in)
-        self.connectPorts(self.atomics[4].outputs["parent"], self.atomics[0].input)
         self.connectPorts(self.atomics[0].glob_outputs["ui"], self.out_ui)
         self.connectPorts(self.in_ui, self.atomics[0].input)
         self.connectPorts(self.atomics[1].glob_outputs["ui"], self.out_ui)

+ 43 - 20
examples/ElevatorBalls/Python/target.py

@@ -359,6 +359,10 @@ class Floor(RuntimeClassBase):
         _running_create_random_ball_3.setAction(self._running_create_random_ball_3_exec)
         _running_create_random_ball_3.setTrigger(Event("update_bounds", None))
         self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_3)
+        _running_create_random_ball_4 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
+        _running_create_random_ball_4.setAction(self._running_create_random_ball_4_exec)
+        _running_create_random_ball_4.setTrigger(Event("transfer_ball", None))
+        self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_4)
         
         # transition /running/wait
         _running_wait_0 = Transition(self, self.states["/running/wait"], [self.states["/running/create_random_ball"]])
@@ -376,7 +380,7 @@ class Floor(RuntimeClassBase):
         self.removeTimer(0)
     
     def _running_create_random_ball_0_exec(self, parameters):
-        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, 10, self.pos['y'], self.elevator_open, self.elev_pos, self.elev_dim, self.elev_vel]))
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, {'x': 10, 'y': self.pos['y']}, {'x': random.uniform(1.0, 5.0), 'y': random.uniform(-5.0, 5.0)}, self.elevator_open, self.elev_pos, self.elev_dim, self.elev_vel]))
     
     def _running_create_random_ball_1_exec(self, parameters):
         print("Elevator opened at:", self.floor_num)
@@ -397,6 +401,14 @@ class Floor(RuntimeClassBase):
         self.elev_vel = elev_vel
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'balls', Event("update_elevator_bounds", None, [elev_pos, elev_dim, elev_vel])]))
     
+    def _running_create_random_ball_4_exec(self, parameters):
+        link_id = parameters[0]
+        prev_floor = parameters[1]
+        new_floor = parameters[2]
+        pos = parameters[3]
+        vel = parameters[4]
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, new_floor, pos, {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)}, self.elevator_open, self.elev_pos, self.elev_dim, self.elev_vel]))
+    
     def _running_wait_0_exec(self, parameters):
         association_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
@@ -663,7 +675,7 @@ class Elevator(RuntimeClassBase):
         RuntimeClassBase.initializeStatechart(self)
 
 class Ball(RuntimeClassBase):
-    def __init__(self, controller, canvas_id, floor_num, x, y, elevator_open, rect_pos, rect_dim, rect_vel):
+    def __init__(self, controller, canvas_id, floor_num, pos, vel, elevator_open, rect_pos, rect_dim, rect_vel):
         RuntimeClassBase.__init__(self, controller)
         
         self.inports["ball_ui"] = controller.addInputPort("ball_ui", self)
@@ -682,9 +694,9 @@ class Ball(RuntimeClassBase):
         self.pos = None
         
         # call user defined constructor
-        Ball.user_defined_constructor(self, canvas_id, floor_num, x, y, elevator_open, rect_pos, rect_dim, rect_vel)
+        Ball.user_defined_constructor(self, canvas_id, floor_num, pos, vel, elevator_open, rect_pos, rect_dim, rect_vel)
     
-    def user_defined_constructor(self, canvas_id, floor_num, x, y, elevator_open, rect_pos, rect_dim, rect_vel):
+    def user_defined_constructor(self, canvas_id, floor_num, pos, vel, elevator_open, rect_pos, rect_dim, rect_vel):
         self.canvas_id = canvas_id;
         
         
@@ -692,15 +704,14 @@ class Ball(RuntimeClassBase):
         
         self.elevator_floor = 0;
         self.elevator_open = elevator_open;
+        
         self.rect_pos = rect_pos
         self.rect_dim = rect_dim
         self.rect_vel = rect_vel
         
-        
-        
         self.r = 5.0;
-        self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
-        self.pos = {'x': x, 'y': y};
+        self.vel = vel;
+        self.pos = pos;
         self.smooth = 0.6; # value between 0 and 1
     
     def user_defined_destructor(self):
@@ -760,20 +771,25 @@ class Ball(RuntimeClassBase):
         # transition /main_behaviour/bouncing
         _main_behaviour_bouncing_0 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
         _main_behaviour_bouncing_0.setAction(self._main_behaviour_bouncing_0_exec)
-        _main_behaviour_bouncing_0.setTrigger(Event("_0after"))
+        _main_behaviour_bouncing_0.setTrigger(None)
+        _main_behaviour_bouncing_0.setGuard(self._main_behaviour_bouncing_0_guard)
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_0)
-        _main_behaviour_bouncing_1 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/ball_delete"]])
-        _main_behaviour_bouncing_1.setTrigger(None)
-        _main_behaviour_bouncing_1.setGuard(self._main_behaviour_bouncing_1_guard)
+        _main_behaviour_bouncing_1 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
+        _main_behaviour_bouncing_1.setAction(self._main_behaviour_bouncing_1_exec)
+        _main_behaviour_bouncing_1.setTrigger(Event("_0after"))
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_1)
-        _main_behaviour_bouncing_2 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
-        _main_behaviour_bouncing_2.setAction(self._main_behaviour_bouncing_2_exec)
-        _main_behaviour_bouncing_2.setTrigger(Event("update_elevator_open", None))
+        _main_behaviour_bouncing_2 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/ball_delete"]])
+        _main_behaviour_bouncing_2.setTrigger(None)
+        _main_behaviour_bouncing_2.setGuard(self._main_behaviour_bouncing_2_guard)
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_2)
         _main_behaviour_bouncing_3 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
         _main_behaviour_bouncing_3.setAction(self._main_behaviour_bouncing_3_exec)
-        _main_behaviour_bouncing_3.setTrigger(Event("update_elevator_bounds", None))
+        _main_behaviour_bouncing_3.setTrigger(Event("update_elevator_open", None))
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_3)
+        _main_behaviour_bouncing_4 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
+        _main_behaviour_bouncing_4.setAction(self._main_behaviour_bouncing_4_exec)
+        _main_behaviour_bouncing_4.setTrigger(Event("update_elevator_bounds", None))
+        self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_4)
         
         # transition /main_behaviour/ball_delete
         _main_behaviour_ball_delete_0 = Transition(self, self.states["/main_behaviour/ball_delete"], [self.states["/deleted"]])
@@ -800,6 +816,13 @@ class Ball(RuntimeClassBase):
         self.circle_id = circle_id
     
     def _main_behaviour_bouncing_0_exec(self, parameters):
+        self.prev_floor = self.floor_num
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("transfer_ball", None, [self.association_name, self.prev_floor, self.elevator_floor, self.pos, self.vel])]))
+    
+    def _main_behaviour_bouncing_0_guard(self, parameters):
+        return self.pos['x'] + self.r > self.rect_pos['x'] + (self.rect_dim['x'] / 2) and self.elevator_open
+    
+    def _main_behaviour_bouncing_1_exec(self, parameters):
         floor_height = ((CANVAS_DIMS[1] - 150) - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
         floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
         floor_pos = {'x': FLOOR_LENGTH / 2, 'y': (CANVAS_DIMS[1] - 150) - (floor_height /2) - ( self.floor_num * (floor_height + FLOOR_SPACE)  )};
@@ -849,15 +872,15 @@ class Ball(RuntimeClassBase):
         self.pos['x'] += self.vel['x']
         self.pos['y'] += self.vel['y']
     
-    def _main_behaviour_bouncing_1_guard(self, parameters):
+    def _main_behaviour_bouncing_2_guard(self, parameters):
         return self.pos['x'] - self.r < 2
     
-    def _main_behaviour_bouncing_2_exec(self, parameters):
+    def _main_behaviour_bouncing_3_exec(self, parameters):
         open_bool = parameters[0]
         self.elevator_open = open_bool
         print("Ball on floor floor_num:", self.floor_num, "went open")
     
-    def _main_behaviour_bouncing_3_exec(self, parameters):
+    def _main_behaviour_bouncing_4_exec(self, parameters):
         pos = parameters[0]
         dim = parameters[1]
         vel = parameters[2]
@@ -902,7 +925,7 @@ class ObjectManager(ObjectManagerBase):
         elif class_name == "Ball":
             instance = Ball(self.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3], construct_params[4], construct_params[5], construct_params[6], construct_params[7])
             instance.associations = {}
-            instance.associations["parent"] = Association("MainApp", 1, 1)
+            instance.associations["parent"] = Association("Floor", 1, 1)
         else:
             raise Exception("Cannot instantiate class " + class_name)
         return instance

+ 37 - 13
examples/ElevatorBalls/sccd.xml

@@ -237,8 +237,8 @@
                             <parameter expr='"Ball"' />
                             <parameter expr="self.canvas_id" />
                             <parameter expr="self.floor_num" />
-                            <parameter expr="10" />
-                            <parameter expr="self.pos['y']" />
+                            <parameter expr="{'x': 10, 'y': self.pos['y']}" />
+                            <parameter expr="{'x': random.uniform(1.0, 5.0), 'y': random.uniform(-5.0, 5.0)}" />
                             <parameter expr="self.elevator_open" />
                             <parameter expr="self.elev_pos" />
                             <parameter expr="self.elev_dim" />
@@ -278,6 +278,25 @@
                             <parameter expr="elev_vel" />
                         </raise>
                     </transition>
+                    <transition event='transfer_ball' target='.'>
+                        <parameter name="link_id" type="int"/>
+                        <parameter name="prev_floor" type="int" />
+                        <parameter name="new_floor" type="int"/>
+                        <parameter name="pos" />
+                        <parameter name="vel" />
+                        <raise scope="cd" event="create_instance">
+                            <parameter expr='"balls"' />
+                            <parameter expr='"Ball"' />
+                            <parameter expr="self.canvas_id" />
+                            <parameter expr="new_floor" />
+                            <parameter expr="pos" />
+                            <parameter expr="{'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)}" />
+                            <parameter expr="self.elevator_open" />
+                            <parameter expr="self.elev_pos" />
+                            <parameter expr="self.elev_dim" />
+                            <parameter expr="self.elev_vel" />
+                        </raise>
+                    </transition>
                 </state>
                 <state id="wait">
                     <transition event="instance_created" target="../create_random_ball">
@@ -476,13 +495,13 @@
         <attribute name="pos" />
         <inport name="ball_ui" />
         <relationships>
-            <association name="parent" class="MainApp" min="1" max="1" />
+            <association name="parent" class="Floor" min="1" max="1" />
         </relationships>
         <constructor>
             <parameter name="canvas_id" />
             <parameter name="floor_num" />
-            <parameter name="x" />
-            <parameter name="y" />
+            <parameter name="pos" />
+            <parameter name="vel" />
             <parameter name="elevator_open" />
             <parameter name="rect_pos" />
             <parameter name="rect_dim" />
@@ -496,15 +515,14 @@
 
                 self.elevator_floor = 0;
                 self.elevator_open = elevator_open;
+
                 self.rect_pos = rect_pos
                 self.rect_dim = rect_dim
                 self.rect_vel = rect_vel
 
-
-
                 self.r = 5.0;
-                self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
-                self.pos = {'x': x, 'y': y};
+                self.vel = vel;
+                self.pos = pos;
                 self.smooth = 0.6; # value between 0 and 1
                 ]]>
             </body>
@@ -541,8 +559,16 @@
                     </transition>
                 </state>
                 <state id="bouncing">
-                    <transition cond="self.pos['x'] - self.r &lt; self.rect_pos['x'] - (self.rect_dim['x'] / 2) and self.elevator_open and self.vel['x'] &lt; 0">
-                        <raise scope="narrow" event="transfer_ball" target="parent" >
+                    <transition cond="self.pos['x'] + self.r &gt; self.rect_pos['x'] + (self.rect_dim['x'] / 2) and self.elevator_open" target=".">
+                        <script>
+                            self.prev_floor = self.floor_num
+                        </script>
+                        <raise scope="narrow" event="transfer_ball" target="'parent'" >
+                            <parameter expr="self.association_name" />
+                            <parameter expr="self.prev_floor" />
+                            <parameter expr="self.elevator_floor" />
+                            <parameter expr="self.pos" />
+                            <parameter expr="self.vel" />
                         </raise>
                     </transition>
                     <transition after="0.02" target=".">
@@ -614,8 +640,6 @@
                             print("Ball on floor floor_num:", self.floor_num, "went open")
                         </script>
                     </transition>
-
-
                     <transition event="update_elevator_bounds" target=".">
                         <parameter name="pos" type="dict" />
                         <parameter name="dim" type="dict" />

+ 3 - 3
examples/TimerEventloop/PyDEVS/target.py

@@ -38,7 +38,7 @@ class MainAppInstance(RuntimeClassBase):
         # call user defined constructor
         MainAppInstance.user_defined_constructor(self)
         port_name = addInputPort("ui", start_port_id, True)
-        atomdevs.state.port_mappings[port_name] = id
+        atomdevs.state.port_mappings[port_name] = None
         port_name = addInputPort("<narrow_cast>", start_port_id)
         atomdevs.state.port_mappings[port_name] = id
         port_name = addInputPort("field_ui", start_port_id + 1)
@@ -226,7 +226,7 @@ class MainApp(ClassBase):
         new_instance = MainAppInstance(self, id, start_port_id)
         return new_instance
 
-def instantiate(self, class_name, construct_params):
+def instantiate(self, class_name):
     instance = {}
     instance["name"] = class_name
     if class_name == "MainApp":
@@ -243,7 +243,7 @@ class ObjectManager(ObjectManagerBase):
         self.state = ObjectManagerState()
         self.input = self.addInPort("input")
         self.output["MainApp"] = self.addOutPort()
-        self.state.createInstance("MainApp", [])
+        self.state.createInstance("MainApp")
 
 class Controller(CoupledDEVS):
     def __init__(self, name):

+ 13 - 7
sccd/compiler/DEVS_generator.py

@@ -58,7 +58,13 @@ class DEVSGenerator(Visitor):
         ################################
         self.writer.beginMethod("instantiate")
         self.writer.addFormalParameter("class_name")
-        self.writer.addFormalParameter("construct_params")
+
+
+
+        #self.writer.addFormalParameter("construct_params")
+
+
+
         self.writer.beginMethodBody()
 
         self.writer.addAssignment("instance", "{}")
@@ -111,7 +117,7 @@ class DEVSGenerator(Visitor):
             self.writer.addAssignment(GLC.SelfProperty(f"output[\"{class_name}\"]"),
                                       GLC.FunctionCall(GLC.SelfProperty("addOutPort")))
 
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("state.createInstance"), [GLC.String(class_diagram.default_class.name), GLC.ArrayExpression()]))
+        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("state.createInstance"), [GLC.String(class_diagram.default_class.name)]))
         self.writer.endMethodBody()
         self.writer.endConstructor()
         self.writer.endClass()
@@ -187,7 +193,7 @@ class DEVSGenerator(Visitor):
         super_classes = []
         if not class_node.super_class_objs:
             if class_node.statechart:
-                super_classes.append("RuntimeClassBase")
+                super_classes.append("RuntimeStatechartBase")
         if class_node.super_classes:
             for super_class in class_node.super_classes:
                 super_classes.append(super_class + "Instance")
@@ -230,7 +236,7 @@ class DEVSGenerator(Visitor):
             )
 
             self.writer.add(GLC.SuperClassMethodCall(
-                "RuntimeClassBase",
+                "RuntimeStatechartBase",
                 "initializeStatechart",
                 []
             ))
@@ -243,7 +249,7 @@ class DEVSGenerator(Visitor):
         ################################
         # Class (Type) 
         ################################
-        self.writer.beginClass(class_node.name, ["ClassBase"])
+        self.writer.beginClass(class_node.name, ["RuntimeClassBase"])
         
         ################################
         # Constructor of Class AtomicDEVS
@@ -252,7 +258,7 @@ class DEVSGenerator(Visitor):
         self.writer.addFormalParameter("name")
 
         self.writer.beginMethodBody()  # constructor body
-        self.writer.beginSuperClassConstructorCall("ClassBase")
+        self.writer.beginSuperClassConstructorCall("RuntimeClassBase")
         self.writer.addActualParameter("name")
         self.writer.endSuperClassConstructorCall()
 
@@ -312,7 +318,7 @@ class DEVSGenerator(Visitor):
 
         self.writer.beginMethodBody()
 
-        self.writer.beginSuperClassConstructorCall("RuntimeClassBase")
+        self.writer.beginSuperClassConstructorCall("RuntimeStatechartBase")
         self.writer.addActualParameter("atomdevs")
         self.writer.addActualParameter("id")
         self.writer.endSuperClassConstructorCall()

+ 5 - 13
sccd/runtime/DEVS_statecharts_core.py

@@ -156,7 +156,7 @@ class Transition:
         return "Transition(%s -> %s)" % (self.source.name, self.targets[0].name)
 
 
-class RuntimeClassBase(object):
+class RuntimeStatechartBase(object):
     def __init__(self, controller, id):
         self.events = EventQueue()
 
@@ -514,7 +514,7 @@ class ClassState():
         self.to_send.append(event)
 
 
-class ClassBase(AtomicDEVS):    
+class RuntimeClassBase(AtomicDEVS):    
     def __init__(self, name):
         AtomicDEVS.__init__(self, name)
 
@@ -760,7 +760,7 @@ class ObjectManagerState():
 
                 ''' allow subclasses to be instantiated '''
                 class_name = association.to_class if len(parameters[2].parameters) == 2 else parameters[2].parameters[2]
-                new_instance = self.createInstance(class_name, parameters[2].parameters[3:])
+                new_instance = self.createInstance(class_name)
 
                 #  Work on index instead of the instance
                 new_instance_index = len(self.instances) - 1
@@ -809,9 +809,9 @@ class ObjectManagerState():
             self.narrow_cast_id += 1
         return port_name
         
-    def createInstance(self, to_class, construct_params = []):
+    def createInstance(self, to_class):
         test = self.addtestInputPort("<narrow_cast>", 0)
-        instance = self.instantiate(to_class, construct_params)
+        instance = self.instantiate(to_class)
         
         self.narrow_cast_ports[len(self.instances)] = test
 
@@ -909,7 +909,6 @@ class ObjectManagerBase(AtomicDEVS):
     def __init__(self, name):
         AtomicDEVS.__init__(self, name)
         self.output = {}
-
         self.to_propagate = ["instance_created", "instance_started", "instance_associated", "instance_disassociated", "instance_deleted"]
 
     def extTransition(self, inputs):
@@ -921,17 +920,10 @@ class ObjectManagerBase(AtomicDEVS):
         return self.state
     
     def intTransition(self):
-        #self.state.to_send.pop(0)
         self.state.to_send.clear()
         return self.state
     
     def outputFnc(self):
-        #out_dict = {}
-        #if not len(self.state.to_send) == 0:
-        #    source, target, message = self.state.to_send[0]
-        #    out_dict[self.output.get(target[0])] = [(source, target, message)]
-        #return out_dict
-
         out_dict = {}
         for source, target, message in self.state.to_send:
             out_dict.setdefault(self.output.get(target[0]), []).append((source, target, message))

+ 0 - 2
sccd/runtime/statecharts_core.py

@@ -629,8 +629,6 @@ class ControllerBase(object):
         for listener in self.output_listeners:
             listener.add(event)
 
-
-
     def addOutputListener(self, ports):
         listener = OutputListener(ports)
         self.output_listeners.append(listener)

tests/1.0) EventlessTransitionTest/config.json → tests/1.1) EventlessTransitionTest/config.json


tests/1.0) EventlessTransitionTest/expected_trace.txt → tests/1.1) EventlessTransitionTest/expected_trace.txt


tests/1.0) EventlessTransitionTest/sccd.xml → tests/1.1) EventlessTransitionTest/sccd.xml


+ 2 - 3
tests/1.12) NonDeterminismTest/expected_trace.txt

@@ -1,4 +1,3 @@
 0.00 MainApp: exit /Y/A
-0.00 MainApp: exit /Y
-0.00 MainApp: transition (/Y -> /D)
-0.00 MainApp: enter /D
+0.00 MainApp: transition (/Y/A -> /Y/B)
+0.00 MainApp: enter /Y/B

+ 1 - 4
tests/1.12) NonDeterminismTest/sccd.xml

@@ -1,8 +1,7 @@
 <?xml version="1.1" ?>
 <diagram author="Sam Pieters" name="NonDeterminismTest">
     <description>
-        Test if nondeterminism works as expected. 
-        There are two states defined in a composite that fire the same moment but these get resolved as the composite state also has an upper trnasition.
+        Test if nondeterminism works as expected. If two transitions fire, the first transition that is defined in the SCCDXML needs to fire.
     </description>
     <class name="MainApp" default="true">
         <scxml initial="Y">
@@ -13,9 +12,7 @@
                 </state>
                 <state id="B" />
                 <state id="C" />
-                <transition target="../D" />
             </state>
-            <state id="D" />
         </scxml>
     </class>
 </diagram>

tests/1.1) AfterTransitionTest/config.json → tests/1.13) NonDeterminismHierarchyTest/config.json


+ 4 - 0
tests/1.13) NonDeterminismHierarchyTest/expected_trace.txt

@@ -0,0 +1,4 @@
+0.00 MainApp: exit /Y/A
+0.00 MainApp: exit /Y
+0.00 MainApp: transition (/Y -> /D)
+0.00 MainApp: enter /D

+ 21 - 0
tests/1.13) NonDeterminismHierarchyTest/sccd.xml

@@ -0,0 +1,21 @@
+<?xml version="1.1" ?>
+<diagram author="Sam Pieters" name="NonDeterminismTest">
+    <description>
+        Test if nondeterminism works as expected. 
+        There are two states defined in a composite that fire the same moment but these get resolved as the composite state also has an upper transition.
+    </description>
+    <class name="MainApp" default="true">
+        <scxml initial="Y">
+            <state id="Y" initial="A"> 
+                <state id="A">
+                    <transition target="../B" />
+                    <transition target="../C" />
+                </state>
+                <state id="B" />
+                <state id="C" />
+                <transition target="../D" />
+            </state>
+            <state id="D" />
+        </scxml>
+    </class>
+</diagram>

tests/1.2) GuardConditionTest/config.json → tests/1.2) AfterTransitionTest/config.json


tests/1.1) AfterTransitionTest/expected_trace.txt → tests/1.2) AfterTransitionTest/expected_trace.txt


tests/1.1) AfterTransitionTest/sccd.xml → tests/1.2) AfterTransitionTest/sccd.xml


tests/1.3) TransitionToItselfTest/config.json → tests/1.3) GuardConditionTest/config.json


tests/1.2) GuardConditionTest/expected_trace.txt → tests/1.3) GuardConditionTest/expected_trace.txt


+ 1 - 2
tests/1.2) GuardConditionTest/sccd.xml

@@ -1,12 +1,11 @@
 <?xml version="1.1" ?>
 <diagram author="Sam Pieters" name="GuardConditionTest">
     <description>
-        Test if the guard condition for a transition works
+        Test if the guard condition for a transition works.
     </description>
     <top>
         VALUE = 5
     </top>
-
     <class name="MainApp" default="true">
         <scxml initial="state1">
             <state id="state1">

tests/1.4) ScriptTransitionTest/config.json → tests/1.4) TransitionToItselfTest/config.json


tests/1.3) TransitionToItselfTest/expected_trace.txt → tests/1.4) TransitionToItselfTest/expected_trace.txt


+ 2 - 2
tests/1.3) TransitionToItselfTest/sccd.xml

@@ -1,7 +1,7 @@
 <?xml version="1.1" ?>
-<diagram author="Sam Pieters" name="AfterTransitionTest">
+<diagram author="Sam Pieters" name="TransitionToItselfTest">
     <description>
-        Check if a state can transition to itself
+        Check if a state can transition to itself.
     </description>
     <class name="MainApp" default="true">
         <constructor>

tests/1.5) ScriptEntryTest/config.json → tests/1.5) ScriptTransitionTest/config.json


tests/1.4) ScriptTransitionTest/expected_trace.txt → tests/1.5) ScriptTransitionTest/expected_trace.txt


tests/1.4) ScriptTransitionTest/sccd.xml → tests/1.5) ScriptTransitionTest/sccd.xml


tests/1.6) ScriptExitTest/config.json → tests/1.6) ScriptEntryTest/config.json


tests/1.5) ScriptEntryTest/expected_trace.txt → tests/1.6) ScriptEntryTest/expected_trace.txt


tests/1.5) ScriptEntryTest/sccd.xml → tests/1.6) ScriptEntryTest/sccd.xml


tests/1.7) CompositeInitialStateTest/config.json → tests/1.7) ScriptExitTest/config.json


tests/1.6) ScriptExitTest/expected_trace.txt → tests/1.7) ScriptExitTest/expected_trace.txt


tests/1.6) ScriptExitTest/sccd.xml → tests/1.7) ScriptExitTest/sccd.xml


tests/10.0) TrafficLightTest/config.json → tests/1.8) CompositeStateTest/config.json


tests/1.7) CompositeInitialStateTest/expected_trace.txt → tests/1.8) CompositeStateTest/expected_trace.txt


+ 1 - 2
tests/1.7) CompositeInitialStateTest/sccd.xml

@@ -1,8 +1,7 @@
 <?xml version="1.1" ?>
-<diagram author="Sam Pieters" name="CompositeInitialStateTest">
+<diagram author="Sam Pieters" name="CompositeStateTest">
     <description>
         Test if composite states are handled correctly.
-        When initial in composite defined, don't go into the first state that is defined but in the initial.
     </description>
     <class name="MainApp" default="true">
         <scxml initial="state1">

tests/10.1) TrafficLightHistory/config.json → tests/10.1) TrafficLightTest/config.json


tests/10.0) TrafficLightTest/expected_trace.txt → tests/10.1) TrafficLightTest/expected_trace.txt


tests/10.0) TrafficLightTest/input.txt → tests/10.1) TrafficLightTest/input.txt


tests/10.0) TrafficLightTest/sccd.xml → tests/10.1) TrafficLightTest/sccd.xml


tests/2.0) GlobalInputTest/config.json → tests/10.2) TrafficLightHistory/config.json


tests/10.1) TrafficLightHistory/expected_trace.txt → tests/10.2) TrafficLightHistory/expected_trace.txt


tests/10.1) TrafficLightHistory/input.txt → tests/10.2) TrafficLightHistory/input.txt


tests/10.1) TrafficLightHistory/sccd.xml → tests/10.2) TrafficLightHistory/sccd.xml


tests/10.2) SimplestBouncingBallsTest/config.json → tests/10.3) SimpleBouncingBallsTest/config.json


tests/10.2) SimplestBouncingBallsTest/expected_trace.txt → tests/10.3) SimpleBouncingBallsTest/expected_trace.txt


tests/10.2) SimplestBouncingBallsTest/input.txt → tests/10.3) SimpleBouncingBallsTest/input.txt


tests/10.2) SimplestBouncingBallsTest/sccd.xml → tests/10.3) SimpleBouncingBallsTest/sccd.xml


tests/10.3) OneBallBouncingBallsTest/config.json → tests/10.4) OneBallBouncingBallsTest/config.json


tests/10.3) OneBallBouncingBallsTest/expected_trace.txt → tests/10.4) OneBallBouncingBallsTest/expected_trace.txt


tests/10.3) OneBallBouncingBallsTest/input.txt → tests/10.4) OneBallBouncingBallsTest/input.txt


tests/10.3) OneBallBouncingBallsTest/sccd.xml → tests/10.4) OneBallBouncingBallsTest/sccd.xml


tests/10.4) CreateExtraFieldBouncingBallsTest/config.json → tests/10.5) CreateExtraFieldBouncingBallsTest/config.json


tests/10.4) CreateExtraFieldBouncingBallsTest/expected_trace.txt → tests/10.5) CreateExtraFieldBouncingBallsTest/expected_trace.txt


tests/10.4) CreateExtraFieldBouncingBallsTest/input.txt → tests/10.5) CreateExtraFieldBouncingBallsTest/input.txt


tests/10.4) CreateExtraFieldBouncingBallsTest/sccd.xml → tests/10.5) CreateExtraFieldBouncingBallsTest/sccd.xml


tests/2.1) GlobalInputCheckTest/config.json → tests/2.1) GlobalInputTest/config.json


tests/2.0) GlobalInputTest/expected_trace.txt → tests/2.1) GlobalInputTest/expected_trace.txt


tests/2.0) GlobalInputTest/input.txt → tests/2.1) GlobalInputTest/input.txt


+ 1 - 1
tests/2.0) GlobalInputTest/sccd.xml

@@ -1,7 +1,7 @@
 <?xml version="1.1" ?>
 <diagram author="Sam Pieters" name="GlobalInputTest">
     <description>
-        Check if the model receives input.
+        Check if a model receives input.
     </description>
     <inport name="Input"/>
     <class name="MainApp" default="true">

tests/2.2) GlobalInputParameterTest/config.json → tests/2.2) GlobalInputCheckTest/config.json


tests/2.1) GlobalInputCheckTest/expected_trace.txt → tests/2.2) GlobalInputCheckTest/expected_trace.txt


tests/2.1) GlobalInputCheckTest/input.txt → tests/2.2) GlobalInputCheckTest/input.txt


tests/2.1) GlobalInputCheckTest/sccd.xml → tests/2.2) GlobalInputCheckTest/sccd.xml


tests/2.7) MultipleInstanceGlobalInputTest/config.json → tests/2.3) GlobalInputParameterTest/config.json


tests/2.2) GlobalInputParameterTest/expected_trace.txt → tests/2.3) GlobalInputParameterTest/expected_trace.txt


tests/2.2) GlobalInputParameterTest/input.txt → tests/2.3) GlobalInputParameterTest/input.txt


+ 1 - 1
tests/2.2) GlobalInputParameterTest/sccd.xml

@@ -1,7 +1,7 @@
 <?xml version="1.1" ?>
 <diagram author="Sam Pieters" name="GlobalInputParameterTest">
     <description>
-        Check if the model receives input with parameters.
+        Check if the global input ports receives events with the right parameters.    
     </description>
     <inport name="Input"/>
     <class name="MainApp" default="true">

tests/2.3) GlobalOutputTest/expected_trace.txt → tests/2.4) GlobalOutputTest/expected_trace.txt


tests/2.3) GlobalOutputTest/sccd.xml → tests/2.4) GlobalOutputTest/sccd.xml


+ 0 - 1
tests/2.4) GlobalTimedOutputTest/expected_trace.txt

@@ -1 +0,0 @@
-0.57 (event name: output_event; port: Outport)

+ 0 - 17
tests/2.4) GlobalTimedOutputTest/sccd.xml

@@ -1,17 +0,0 @@
-<?xml version="1.1" ?>
-<diagram author="Sam Pieters" name="GlobalTimedOutputTest">
-    <description>
-        Check if the model raises a timed output.
-    </description>
-    <outport name="Outport"/>
-    <class name="MainApp" default="true">
-        <scxml initial="state1">
-            <state id="state1">
-                <transition after="0.57" target="../state2">
-                    <raise port="Outport" event="output_event" />
-                </transition>
-            </state>
-            <state id="state2" />
-        </scxml>
-    </class>
-</diagram>

+ 1 - 1
tests/2.5) GlobalTimedOutputTest/expected_trace.txt

@@ -1 +1 @@
-1.00 (event name: test_event; port: Outport)
+0.57 (event name: output_event; port: Outport)

+ 5 - 7
tests/2.5) GlobalTimedOutputTest/sccd.xml

@@ -1,19 +1,17 @@
 <?xml version="1.1" ?>
 <diagram author="Sam Pieters" name="GlobalTimedOutputTest">
     <description>
-        Check if the model outputs one event on the right time (sends it different than 2.4).
+        Check if the model raises a timed output. The raised event is trigger within a transition.
     </description>
     <outport name="Outport"/>
     <class name="MainApp" default="true">
         <scxml initial="state1">
             <state id="state1">
-                <transition after="1" target="../end" />
-            </state>
-            <state id="end">
-                <onentry>
-                    <raise port="Outport" event="test_event" />
-                </onentry>
+                <transition after="0.57" target="../state2">
+                    <raise port="Outport" event="output_event" />
+                </transition>
             </state>
+            <state id="state2" />
         </scxml>
     </class>
 </diagram>

+ 1 - 0
tests/2.6) GlobalTimedOutputTest/expected_trace.txt

@@ -0,0 +1 @@
+1.00 (event name: test_event; port: Outport)

+ 19 - 0
tests/2.6) GlobalTimedOutputTest/sccd.xml

@@ -0,0 +1,19 @@
+<?xml version="1.1" ?>
+<diagram author="Sam Pieters" name="GlobalTimedOutputTest">
+    <description>
+        Check if the model outputs one event on the right time (sends it different than 2.4). The event is raised on the entry of a new state.
+    </description>
+    <outport name="Outport"/>
+    <class name="MainApp" default="true">
+        <scxml initial="state1">
+            <state id="state1">
+                <transition after="1" target="../end" />
+            </state>
+            <state id="end">
+                <onentry>
+                    <raise port="Outport" event="test_event" />
+                </onentry>
+            </state>
+        </scxml>
+    </class>
+</diagram>

tests/2.6) GlobalIOTest/expected_trace.txt → tests/2.7) GlobalIOTest/expected_trace.txt


tests/2.6) GlobalIOTest/input.txt → tests/2.7) GlobalIOTest/input.txt


+ 1 - 1
tests/2.6) GlobalIOTest/sccd.xml

@@ -1,7 +1,7 @@
 <?xml version="1.1" ?>
 <diagram author="Sam Pieters" name="GlobalIOTest">
     <description>
-        Check if the model receives input and directly sends an output
+        Check if the model responds to an input with an output over its global ports.
     </description>
     <inport name="Inport"/>
     <outport name="Outport"/>

tests/5.0) PrivateInPortTest/config.json → tests/2.8) MultipleInstancesGlobalInputTest/config.json


tests/2.7) MultipleInstanceGlobalInputTest/expected_trace.txt → tests/2.8) MultipleInstancesGlobalInputTest/expected_trace.txt


tests/2.7) MultipleInstanceGlobalInputTest/input.txt → tests/2.8) MultipleInstancesGlobalInputTest/input.txt


+ 1 - 1
tests/2.7) MultipleInstanceGlobalInputTest/sccd.xml

@@ -1,5 +1,5 @@
 <?xml version="1.1" ?>
-<diagram author="Sam Pieters" name="MultipleInstanceGlobalInputTest">
+<diagram author="Sam Pieters" name="MultipleInstancesGlobalInputTest">
     <description>
         Check if multiple SCCD classes receive the events from the inport
     </description>

tests/2.8) MultipleOutputTest/expected_trace.txt → tests/2.9) MultipleOutputTest/expected_trace.txt


tests/2.8) MultipleOutputTest/sccd.xml → tests/2.9) MultipleOutputTest/sccd.xml


+ 0 - 1
tests/3.0) ClassCreation/expected_trace.txt

@@ -1 +0,0 @@
-0.00 (event name: instance_created_succesfully; port: Outport; parameters: ['linkA[0]'])

+ 3 - 0
tests/3.1) ClassCreation/config.json

@@ -0,0 +1,3 @@
+{
+    "trace": ["statechart", "external", "internal"]
+}

+ 6 - 0
tests/3.1) ClassCreation/expected_trace.txt

@@ -0,0 +1,6 @@
+0.00 (event name: create_instance; port: None; parameters: [0, 'linkA', 'A'])
+0.00 (event name: instance_created; port: None; parameters: ['linkA[0]'])
+0.00 MainApp: exit /state1
+0.00 MainApp: transition (/state1 -> /state2)
+0.00 MainApp: enter /state2
+0.00 (event name: instance_created_succesfully; port: Outport; parameters: ['linkA[0]'])

tests/3.0) ClassCreation/sccd.xml → tests/3.1) ClassCreation/sccd.xml


+ 0 - 3
tests/3.1) ClassInitialisation/expected_trace.txt

@@ -1,3 +0,0 @@
-0.00 (event name: instance_created_succesfully; port: Outport; parameters: ['linkA[0]'])
-0.00 (event name: statechart_started_succesfully; port: Outport)
-0.00 (event name: instance_started_succesfully; port: Outport; parameters: ['linkA[0]'])

tests/3.4) MultipleClassesInitialisation/expected_trace.txt → tests/3.10) DeleteBadFromNonParent/expected_trace.txt


tests/3.9) DeleteBadFromNonParent/sccd.xml → tests/3.10) DeleteBadFromNonParent/sccd.xml


+ 0 - 0
tests/3.10) DeleteGoodFromNonParent/expected_trace.txt


Деякі файли не було показано, через те що забагато файлів було змінено