Преглед изворни кода

fixed bug where the instances where a set and not a list. If searched on index --> undefined behaviour. Hide implementation details and improved ui wrapper so that we can use 1 ui for every platform

sampieters пре 1 година
родитељ
комит
f0906e3bf2

+ 0 - 1
README.md

@@ -97,6 +97,5 @@ python3 runner.py
 ### Timer
 
 ## TODO
-1) fill parameters in constructor (e.g. Button, Ball).
 2) self.inports["elem"] should only be "elem"
 3) Convert DEVui_v2 to ui_v2

+ 93 - 146
examples/BouncingBalls/PyDEVS/best_target.py

@@ -209,10 +209,11 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         self.outputs["fields"] = self.addOutPort("fields")
         self.obj_manager_in = self.addInPort("obj_manager_in")
         self.input = self.addInPort("input")
-        self.instances.add(MainAppInstance(self))
+        self.instances.append(MainAppInstance(self))
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.obj_manager_in in inputs:
@@ -224,64 +225,47 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
                 tem = eval(input)
                 self.addInput(tem)
             elif input[3].name == "create_instance":
-                self.instances.add(MainAppInstance(self))
+                new_instance = MainAppInstance(self)
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance("fields[0]")
                 ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].parameters[0]]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
                 association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[2]]
                 p = instance.associations.get(association[0])
                 if p:
                     p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                #instance.associations['fields'].instances[0] = input[3].parameters[0]
-
-
-
-                #association = self.processAssociationReference(input[3].parameters[0])[0]
-                #instance = list(self.instances)[input[2]]
-                #p = instance.associations.get(association[0])
-                #if p:
-                #    p.addInstance(input[3].parameters[0])
-                #instance.addEvent(input[3])
-
-                
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[2]]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
-                ev = input[3]
-                self.addInput(ev, force_internal=True)
+                pass
             else:
                 ev = input[3]
                 self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
@@ -319,8 +303,6 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         return self.next_time
 
 class FieldInstance(RuntimeClassBase):
-    num_instances = 0
-
     def __init__(self, atomdevs):
         RuntimeClassBase.__init__(self, atomdevs)
         self.associations = {}
@@ -343,9 +325,7 @@ class FieldInstance(RuntimeClassBase):
         
         # call user defined constructor
         FieldInstance.user_defined_constructor(self)
-
-        self.inports['field_ui'] = ('field_ui', FieldInstance.num_instances)
-        FieldInstance.num_instances += 1
+        self.inports["field_ui"] = ('field_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self):
         pass
@@ -508,10 +488,10 @@ class FieldInstance(RuntimeClassBase):
         self.states["/root/running"].addTransition(_root_running_0)
     
     def _root_creating_window_enter(self):
-        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [800, 600, "BouncingBalls",  self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [800, 600, "BouncingBalls", self.inports['field_ui']]))
     
     def _root_creating_canvas_enter(self):
-        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_WIDTH, CANVAS_HEIGHT, {'background':'#eee'},  self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_WIDTH, CANVAS_HEIGHT, {'background':'#eee'}, self.inports['field_ui']]))
     
     def _root_creating_button_enter(self):
         self.big_step.outputEventOM(Event("create_instance", None, [self, "buttons", "Button", self.window_id, 'create_new_field', 'Spawn New Window']))
@@ -527,15 +507,15 @@ class FieldInstance(RuntimeClassBase):
     def _root_creating_window_0_exec(self, parameters):
         window_id = parameters[0]
         self.window_id = window_id
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.WINDOW_CLOSE, 'window_close',  self.inports['field_ui']]))
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.KEY_PRESS, 'key_press',  self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.WINDOW_CLOSE, 'window_close', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.KEY_PRESS, 'key_press', self.inports['field_ui']]))
     
     def _root_creating_canvas_0_exec(self, parameters):
         canvas_id = parameters[0]
         self.canvas_id = canvas_id
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RIGHT_CLICK, 'right_click',  self.inports['field_ui']]))
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move',  self.inports['field_ui']]))
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release',  self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RIGHT_CLICK, 'right_click', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release', self.inports['field_ui']]))
     
     def _root_creating_button_0_exec(self, parameters):
         association_name = parameters[0]
@@ -594,6 +574,7 @@ class Field(AtomicDEVS, ObjectManagerBase):
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.field_ui in inputs:
@@ -608,66 +589,52 @@ class Field(AtomicDEVS, ObjectManagerBase):
                 self.addInput(tem)
             elif input[3].name == "create_instance":
                 new_instance = FieldInstance(self)
-                self.instances.add(new_instance)
-
-                #TODO: hardcoded but needs to be fixed
+                self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance(f"mainapp[0]")
-
+                    p.addInstance("fields[0]")
                 ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
-
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
                 association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[2]]
                 p = instance.associations.get(association[0])
                 if p:
                     p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[2]]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
-                ev = input[3]
-                self.addInput(ev, force_internal=True)
+                pass
             else:
                 ev = input[3]
                 self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
         self.handleInput()
         self.stepAll()
         next_earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
-
         if not (len(self.to_send) == 0):
             self.next_time = 0
         elif next_earliest == INFINITY:
@@ -699,8 +666,6 @@ class Field(AtomicDEVS, ObjectManagerBase):
         return self.next_time
 
 class ButtonInstance(RuntimeClassBase):
-    num_instances = 0
-
     def __init__(self, atomdevs, window_id, event_name, button_text):
         RuntimeClassBase.__init__(self, atomdevs)
         self.associations = {}
@@ -722,9 +687,7 @@ class ButtonInstance(RuntimeClassBase):
         
         # call user defined constructor
         ButtonInstance.user_defined_constructor(self, window_id, event_name, button_text)
-
-        self.inports['button_ui'] = ('button_ui', ButtonInstance.num_instances)
-        ButtonInstance.num_instances += 1
+        self.inports["button_ui"] = ('button_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self, window_id, event_name, button_text):
         self.window_id = window_id;
@@ -767,12 +730,12 @@ class ButtonInstance(RuntimeClassBase):
         self.states["/running"].addTransition(_running_0)
     
     def _creating_button_enter(self):
-        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, self.event_name,  self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, self.event_name, self.inports['button_ui']]))
     
     def _creating_button_0_exec(self, parameters):
         button_id = parameters[0]
         self.button_id = button_id
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [button_id, ui.EVENTS.MOUSE_CLICK, "mouse_click",  self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [button_id, ui.EVENTS.MOUSE_CLICK, "mouse_click", self.inports['button_ui']]))
     
     def _running_0_exec(self, parameters):
         x = parameters[0]
@@ -806,6 +769,7 @@ class Button(AtomicDEVS, ObjectManagerBase):
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.button_ui in inputs:
@@ -820,57 +784,46 @@ class Button(AtomicDEVS, ObjectManagerBase):
                 self.addInput(tem)
             elif input[3].name == "create_instance":
                 new_instance = ButtonInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
-                self.instances.add(new_instance)
-
-                #TODO: hardcoded but needs to be fixed
+                self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance(f"fields[0]")
-
-
-
+                    p.addInstance("fields[0]")
                 ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                instance = list(self.instances)[input[2]]
-                instance.user_defined_destructor()
-                instance.stop()
-                ev = Event("instance_deleted", None, parameters=[self, input[0]])
-                self.to_send.append((self.name, input[1], input[2], ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
-                instance = list(self.instances)[input[2]]
+                association = self.processAssociationReference(input[3].parameters[0])[0]
+                instance = self.instances[input[2]]
+                p = instance.associations.get(association[0])
+                if p:
+                    p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[2]]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
+                pass
+            else:
                 ev = input[3]
-                self.addInput(ev, force_internal=True)
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
@@ -908,8 +861,6 @@ class Button(AtomicDEVS, ObjectManagerBase):
         return self.next_time
 
 class BallInstance(RuntimeClassBase):
-    num_instances = 0
-
     def __init__(self, atomdevs, canvas_id, x, y):
         RuntimeClassBase.__init__(self, atomdevs)
         self.associations = {}
@@ -930,9 +881,7 @@ class BallInstance(RuntimeClassBase):
         
         # call user defined constructor
         BallInstance.user_defined_constructor(self, canvas_id, x, y)
-
-        self.inports['ball_ui'] = ('ball_ui', BallInstance.num_instances)
-        BallInstance.num_instances += 1
+        self.inports["ball_ui"] = ('ball_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self, canvas_id, x, y):
         self.canvas_id = canvas_id;
@@ -1040,7 +989,7 @@ class BallInstance(RuntimeClassBase):
         self.states["/main_behaviour/selected"].addTransition(_main_behaviour_selected_1)
     
     def _main_behaviour_creating_circle_enter(self):
-        self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.r, {'fill':'#000'},  self.inports['ball_ui']]))
+        self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.r, {'fill':'#000'}, self.inports['ball_ui']]))
     
     def _main_behaviour_bouncing_enter(self):
         self.addTimer(0, 0.02)
@@ -1056,9 +1005,9 @@ class BallInstance(RuntimeClassBase):
         canvas_id = parameters[0]
         circle_id = parameters[1]
         self.circle_id = circle_id
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'mouse_press',  self.inports['ball_ui']]))
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move',  self.inports['ball_ui']]))
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release',  self.inports['ball_ui']]))
+        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'mouse_press', self.inports['ball_ui']]))
+        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['ball_ui']]))
+        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release', self.inports['ball_ui']]))
     
     def _main_behaviour_bouncing_0_exec(self, parameters):
         # Invert velocity when colliding with canvas border:
@@ -1142,7 +1091,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
-        self.simulated_time += self.elapsed
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.ball_ui in inputs:
@@ -1156,47 +1105,46 @@ class Ball(AtomicDEVS, ObjectManagerBase):
                 tem = eval(input)
                 self.addInput(tem)
             elif input[3].name == "create_instance":
-                self.instances.add(BallInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3]))
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((self.name, input[0], input[2], ev))
+                new_instance = BallInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance("fields[0]")
+                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"], len(self.instances)-1)
+                self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[3].parameters[0]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[input[3].parameters[0]])
-                self.to_send.append((input[0], input[1], input[3].parameters[0], ev))
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
+                self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[])
-                self.to_send.append((self.name, input[0], input[2], ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
                 association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = list(self.instances)[association[1]]
+                instance = self.instances[input[2]]
+                p = instance.associations.get(association[0])
+                if p:
+                    p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[3].parameters[0]]
+                instance = self.instances[input[3].instance]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
+                pass
+            else:
                 ev = input[3]
-                self.addInput(ev, force_internal=True)
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        # TODO: self.simulated_time added here, do this everywhere
         earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
@@ -1210,7 +1158,6 @@ class Ball(AtomicDEVS, ObjectManagerBase):
             self.next_time = INFINITY
         else:
             self.next_time = next_earliest - earliest
-            #helping = self.time_next[0] - self.time_last[0]
         return self.instances
     
     def outputFnc(self):
@@ -1237,7 +1184,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
 
 class ObjectManagerState:
     def __init__(self):
-        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, None))]
+        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, [0]))]
 
 class ObjectManager(AtomicDEVS):
     def __init__(self, name):

+ 6 - 7
examples/BouncingBalls/PyDEVS/runner.py

@@ -1,8 +1,7 @@
-from pypdevs.simulator import Simulator
-import examples.BouncingBalls.PyDEVS.best_target as target
-
-from tkinter import *
-from sccd.runtime.libs.DEVui_v2 import UI
+import tkinter as tk
+import target as target
+from sccd.runtime.libs.ui_v2 import UI
+from sccd.runtime.DEVS_loop import DEVSSimulator
 
 class OutputListener:
 	def __init__(self, ui):
@@ -17,9 +16,9 @@ if __name__ == '__main__':
 	model = target.Controller(name="controller")
 	refs = {"ui": model.ui, "field_ui": model.atomic1.field_ui, "button_ui": model.atomic2.button_ui, "ball_ui": model.atomic3.ball_ui}
 
-	tkroot = Tk()
+	tkroot = tk.Tk()
 	tkroot.withdraw()
-	sim = Simulator(model)
+	sim = DEVSSimulator(model)
 	sim.setRealTime(True)
 	sim.setRealTimeInputFile(None)
 	sim.setRealTimePorts(refs)

+ 118 - 90
examples/BouncingBalls/PyDEVS/target.py

@@ -209,10 +209,11 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         self.outputs["fields"] = self.addOutPort("fields")
         self.obj_manager_in = self.addInPort("obj_manager_in")
         self.input = self.addInPort("input")
-        self.instances.add(MainAppInstance(self))
+        self.instances.append(MainAppInstance(self))
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.obj_manager_in in inputs:
@@ -224,46 +225,47 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
                 tem = eval(input)
                 self.addInput(tem)
             elif input[3].name == "create_instance":
-                self.instances.add(MainAppInstance(self))
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
+                new_instance = MainAppInstance(self)
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance("fields[0]")
+                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
-                instance = list(self.instances)[input[2]]
+                association = self.processAssociationReference(input[3].parameters[0])[0]
+                instance = self.instances[input[2]]
+                p = instance.associations.get(association[0])
+                if p:
+                    p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
+                pass
+            else:
                 ev = input[3]
-                self.addInput(ev, force_internal=True)
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
@@ -323,6 +325,7 @@ class FieldInstance(RuntimeClassBase):
         
         # call user defined constructor
         FieldInstance.user_defined_constructor(self)
+        self.inports["field_ui"] = ('field_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self):
         pass
@@ -571,6 +574,7 @@ class Field(AtomicDEVS, ObjectManagerBase):
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.field_ui in inputs:
@@ -584,46 +588,47 @@ class Field(AtomicDEVS, ObjectManagerBase):
                 tem = eval(input)
                 self.addInput(tem)
             elif input[3].name == "create_instance":
-                self.instances.add(FieldInstance(self))
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
+                new_instance = FieldInstance(self)
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance("fields[0]")
+                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
-                instance = list(self.instances)[input[2]]
+                association = self.processAssociationReference(input[3].parameters[0])[0]
+                instance = self.instances[input[2]]
+                p = instance.associations.get(association[0])
+                if p:
+                    p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
+                pass
+            else:
                 ev = input[3]
-                self.addInput(ev, force_internal=True)
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
@@ -682,6 +687,7 @@ class ButtonInstance(RuntimeClassBase):
         
         # call user defined constructor
         ButtonInstance.user_defined_constructor(self, window_id, event_name, button_text)
+        self.inports["button_ui"] = ('button_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self, window_id, event_name, button_text):
         self.window_id = window_id;
@@ -763,6 +769,7 @@ class Button(AtomicDEVS, ObjectManagerBase):
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.button_ui in inputs:
@@ -776,46 +783,64 @@ class Button(AtomicDEVS, ObjectManagerBase):
                 tem = eval(input)
                 self.addInput(tem)
             elif input[3].name == "create_instance":
-                self.instances.add(ButtonInstance(self))
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
+                new_instance = ButtonInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance("fields[0]")
+                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                instance = self.instances[input[3].instance]
+                try:
+                    for assoc_name in instance.associations:
+                        if assoc_name != 'parent':
+                            traversal_list = self.processAssociationReference(assoc_name)
+                            instances = self.getInstances(i["instance"], traversal_list)
+                            if len(instances) > 0:
+                                raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (assoc_name, len(instances), assoc_name))
+                    #del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
+                    #association.removeInstance(instance)
+                    self.instances.remove(instance)
+                    self.eventless.discard(instance)
+                except AssociationException as exception:
+                    raise RuntimeException("Error removing instance from association '" + assoc_name + "': " + str(exception))
+                instance.user_defined_destructor()
+                instance.stop()
+                ev = Event("instance_deleted", None, parameters = [input[0]])
+                self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
-                instance = list(self.instances)[input[2]]
+                association = self.processAssociationReference(input[3].parameters[0])[0]
+                instance = self.instances[input[2]]
+                p = instance.associations.get(association[0])
+                if p:
+                    p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
+                pass
+            else:
                 ev = input[3]
-                self.addInput(ev, force_internal=True)
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
@@ -873,6 +898,7 @@ class BallInstance(RuntimeClassBase):
         
         # call user defined constructor
         BallInstance.user_defined_constructor(self, canvas_id, x, y)
+        self.inports["ball_ui"] = ('ball_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self, canvas_id, x, y):
         self.canvas_id = canvas_id;
@@ -1082,6 +1108,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
         self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.ball_ui in inputs:
@@ -1095,46 +1122,47 @@ class Ball(AtomicDEVS, ObjectManagerBase):
                 tem = eval(input)
                 self.addInput(tem)
             elif input[3].name == "create_instance":
-                self.instances.add(BallInstance(self))
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
+                new_instance = BallInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance("fields[0]")
+                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
                 self.to_send.append((input[1], input[0], input[2], ev))
             elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[f"{input[0]}[{input[2]}]"])
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
                 self.to_send.append((input[0], input[1], input[2], ev))
             elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((self.name, TODO, TODO, ev))
+                pass
             elif input[3].name == "instance_created":
-                instance = list(self.instances)[input[2]]
+                association = self.processAssociationReference(input[3].parameters[0])[0]
+                instance = self.instances[input[2]]
+                p = instance.associations.get(association[0])
+                if p:
+                    p.addInstance(input[3].parameters[0])
                 instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
             elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
+                instance = self.instances[input[3].instance]
                 instance.addEvent(input[3])
             elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
+                pass
             elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
+                pass
+            else:
                 ev = input[3]
-                self.addInput(ev, force_internal=True)
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
@@ -1173,7 +1201,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
 
 class ObjectManagerState:
     def __init__(self):
-        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, None))]
+        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, [0], 0))]
 
 class ObjectManager(AtomicDEVS):
     def __init__(self, name):

Разлика између датотеке није приказан због своје велике величине
+ 0 - 1255
examples/BouncingBalls/PyDEVS/testtarget.py


+ 34 - 27
sccd/compiler/DEVS_generator.py

@@ -60,7 +60,7 @@ class DEVSGenerator(Visitor):
         self.writer.beginConstructor()
         self.writer.beginMethodBody()
 
-        self.writer.addAssignment(GLC.SelfProperty("to_send"), f"[(None, \"{class_diagram.default_class.name}\", 0, Event(\"start_instance\", None, None))]")
+        self.writer.addAssignment(GLC.SelfProperty("to_send"), f"[(None, \"{class_diagram.default_class.name}\", 0, Event(\"start_instance\", None, [0], 0))]")
 
         self.writer.endMethodBody()
         self.writer.endConstructor()
@@ -288,6 +288,9 @@ class DEVSGenerator(Visitor):
             self.writer.addActualParameter(p.getIdent())
         self.writer.endSuperClassMethodCall()
 
+        for inp in class_node.inports:
+            self.writer.addAssignment(GLC.SelfProperty(f"inports[\"{inp}\"]"), f"(\'{inp}\', len(atomdevs.instances))")
+
 
         self.writer.endMethodBody()
         self.writer.endConstructor()
@@ -364,7 +367,7 @@ class DEVSGenerator(Visitor):
         self.writer.addFormalParameter("inputs")
         self.writer.beginMethodBody()
 
-        #self.writer.addAssignment(GLC.SelfProperty("simulated_time"), GLC.AdditionExpression(GLC.SelfProperty("simulated_time"), GLC.SelfProperty("elapsed")))
+        self.writer.addAssignment(GLC.SelfProperty("simulated_time"), GLC.AdditionExpression(GLC.SelfProperty("simulated_time"), GLC.SelfProperty("elapsed")))
         self.writer.addAssignment(GLC.SelfProperty("next_time"), "0")
         self.writer.addAssignment("all_inputs", "[]")
 
@@ -384,65 +387,69 @@ class DEVSGenerator(Visitor):
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("create_instance")))
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("instances.add"), [GLC.FunctionCall(f"{class_node.name}Instance", ["self"])]))
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_created\"", "None", "parameters=[f\"{input[3].parameters[0]}[{len(self.instances)-1}]\"]"]))
+
+        parameters = [GLC.SelfExpression()]
+        for i, _ in enumerate(constructor.parameters):
+            parameters.append(f"input[3].parameters[{i+1}]")
+
+        self.writer.addAssignment("new_instance", GLC.FunctionCall(f"{class_node.name}Instance", parameters))
+        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("instances.append"), ["new_instance"]))
+
+        self.writer.addAssignment("p", "new_instance.associations.get(\"parent\")")
+        self.writer.beginIf("p")
+        self.writer.add(GLC.FunctionCall("p.addInstance", [GLC.String("fields[0]")]))
+        self.writer.endIf()
+
+
+        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_created\"", "None", "[f\"{input[3].parameters[0]}[{len(self.instances)-1}]\"]"]))
         self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(input[1], input[0], input[2], ev)"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("start_instance")))
-        # TODO: quick fix, self.instances should not be a set because need to acces at index
-        self.writer.addAssignment("instance", "list(self.instances)[input[2]]")
+        self.writer.addAssignment("instance", "self.instances[input[3].instance]")
         self.writer.add(GLC.FunctionCall("instance.start"))
 
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_started\"", "None", "parameters=[f\"{input[0]}[{input[2]}]\"]"]))
+        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_started\"", "None", "[f\"{input[0]}[{len(self.instances)-1}]\"], input[3].instance"]))
         self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(input[0], input[1], input[2], ev)"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("delete_instance")))
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_deleted\"", "None", "parameters=[TODO]"]))
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(self.name, TODO, TODO, ev)"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("associate_instance")))
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_associated\"", "None", "parameters=[TODO]"]))
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(self.name, TODO, TODO, ev)"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("disassociate_instance")))
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_disassociated\"", "None", "parameters=[TODO]"]))
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(self.name, TODO, TODO, ev)"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_created")))
-        self.writer.addAssignment("instance", "list(self.instances)[input[2]]")
+        self.writer.addAssignment("association", "self.processAssociationReference(input[3].parameters[0])[0]")
+        self.writer.addAssignment("instance", "self.instances[input[2]]")
+        self.writer.addAssignment("p", "instance.associations.get(association[0])")
+        self.writer.beginIf("p")
+        self.writer.add(GLC.FunctionCall("p.addInstance", ["input[3].parameters[0]"]))
+        self.writer.endIf()
         self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
-        self.writer.addAssignment("instance.associations['fields'].instances[0]", "input[3].parameters[0]")
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_started")))
-        self.writer.addAssignment("instance", "list(self.instances)[input[2]]")
+        self.writer.addAssignment("instance", "self.instances[input[3].instance]")
         self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_deleted")))
-        self.writer.addAssignment("instance", "list(self.instances)[input[2]]")
-        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_associated")))
-        self.writer.addAssignment("instance", "list(self.instances)[input[2]]")
-        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
         self.writer.endElseIf()
 
         self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_disassociated")))
-        self.writer.addAssignment("instance", "list(self.instances)[input[2]]")
-        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("set_association_name")))
+        self.writer.beginElse()
         self.writer.addAssignment("ev", "input[3]")
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addInput"), ["ev", "force_internal=True"]))
-        self.writer.endElseIf()
+        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addInput"), ["ev"]))
+        self.writer.endElse()
         
         self.writer.endForLoopIterateArray()
 
@@ -452,7 +459,7 @@ class DEVSGenerator(Visitor):
 
         self.writer.beginMethod("intTransition")
         self.writer.beginMethodBody()
-        self.writer.addAssignment("earliest", GLC.FunctionCall("min", [GLC.SelfProperty("getEarliestEventTime()"), GLC.SelfProperty("input_queue.getEarliestTime()")]))
+        self.writer.addAssignment("earliest", GLC.FunctionCall("min", [GLC.SelfProperty("getEarliestEventTime()"), GLC.AdditionExpression(GLC.SelfProperty("simulated_time"), GLC.SelfProperty("input_queue.getEarliestTime()"))]))
         self.writer.beginIf(GLC.NotExpression(GLC.EqualsExpression("earliest", "INFINITY")))
         self.writer.addAssignment(GLC.SelfProperty("simulated_time"), "earliest")
         self.writer.endIf()
@@ -568,7 +575,7 @@ class DEVSGenerator(Visitor):
                 GLC.FunctionCall(GLC.Property("controller", "addOutputPort"), [GLC.String(p), GLC.SelfExpression()]))
 
         if constructor.parent_class.name == constructor.parent_class.class_diagram.default_class.name:
-            self.writer.add(GLC.FunctionCall(GLC.SelfProperty("instances.add"), [f"{constructor.parent_class.name}Instance(self)"]))
+            self.writer.add(GLC.FunctionCall(GLC.SelfProperty("instances.append"), [f"{constructor.parent_class.name}Instance(self)"]))
 
         self.writer.addAssignment(GLC.SelfProperty("next_time"), "INFINITY")
 

+ 11 - 0
sccd/runtime/DEVS_loop.py

@@ -0,0 +1,11 @@
+from pypdevs.simulator import Simulator
+
+class DEVSSimulator(Simulator):
+	def __init__(self, model):
+		Simulator.__init__(self, model)	
+	
+	def addInput(self, event):
+		event_string = f"Event(\"{event.name}\",\"{event.port[0]}\",{event.parameters},{event.port[1]})"
+		event_string = event_string.replace(" ", "")
+		interrupt_string = f"{event.port[0]} {event_string}"
+		self.realtime_interrupt(interrupt_string)

+ 3 - 15
sccd/runtime/DEVS_statecharts_core.py

@@ -681,7 +681,7 @@ class ObjectManagerBase(object):
         self.to_send = []
 
         self.events = EventQueue()
-        self.instances = set() # a set of RuntimeClassBase instances
+        self.instances = []
         self.instance_times = []
         self.eventless = set()
         self.regex_pattern = re.compile("^([a-zA-Z_]\w*)(?:\[(\d+)\])?$")
@@ -700,18 +700,6 @@ class ObjectManagerBase(object):
 
         self.lock = threading.Condition()
     
-    #def getEarliestEventTime(self):
-        #while self.instance_times and self.instance_times[0][0] < self.instance_times[0][1].earliest_event_time:
-        #    heappop(self.instance_times)
-        #earliest_event_time = min(INFINITY if not self.instance_times else self.instance_times[0][0], self.events.getEarliestTime())
-
-        #return  min(earliest_event_time, self.input_queue.getEarliestTime())
-    
-    #def getEarliestEventTime(self):
-    #    while self.instance_times and self.instance_times[0][0] < self.instance_times[0][1].earliest_event_time:
-    #        heappop(self.instance_times)
-    #    return min(INFINITY if not self.instance_times else self.instance_times[0][0], self.events.getEarliestTime())
-    
     def getEarliestEventTime(self):
         with self.lock:
             while self.instance_times and self.instance_times[0][0] < self.instance_times[0][1].earliest_event_time:
@@ -832,7 +820,7 @@ class ObjectManagerBase(object):
             for i in self.getInstances(source, traversal_list):
                 #i["instance"].start()
                 # TODO: start instance over a link from mainapp to field
-                self.to_send.append((i['assoc_name'], i['to_class'], 0, Event("start_instance", None, [i['instance']])))
+                self.to_send.append((i['assoc_name'], i['to_class'], 0, Event("start_instance", None, [], i['instance'])))
 
 
 
@@ -904,7 +892,7 @@ class ObjectManagerBase(object):
             association = source.associations[traversal_list[0][0]]
             
             for i in instances:
-                self.to_send.append((i['assoc_name'], i['to_class'], 0, Event("delete_instance", None, None)))
+                self.to_send.append((i['assoc_name'], i['to_class'], 0, Event("delete_instance", None, None, i['instance'])))
                 #try:
                     #for assoc_name in i["instance"].associations:
                     #    if assoc_name != 'parent':

+ 0 - 135
sccd/runtime/libs/DEVui.py

@@ -1,135 +0,0 @@
-"""
- *REALLY* Small framework for creating/manipulating/deleting gui elements in Tkinter.
-
- NOTE: keep this synced with ui.js
-
- Author: Raphael Mannadiar
- Date: 2014/08/21
-"""
-
-import sys
-try:
-    import Tkinter as tk
-except ImportError:
-    import tkinter as tk
-
-from sccd.runtime.libs.drawing import drawing
-from sccd.runtime.libs.utils import utils
-
-from sccd.runtime.statecharts_core import Event
-
-
-class ui:
-    simulator = None
-    window = None
-    __nextWindowId = 0
-
-    EVENTS = utils._bunch(
-        KEY_PRESS =             '<Key>',
-        MOUSE_CLICK =             '<Button>',
-        MOUSE_MOVE =             '<Motion>',
-        MOUSE_PRESS =            '<ButtonPress>',
-        MOUSE_RELEASE =        '<ButtonRelease>',
-        MOUSE_RIGHT_CLICK =    '<Button-2>' if sys.platform == "darwin" else '<Button-3>',
-        WINDOW_CLOSE =         'WM_DELETE_WINDOW');
-
-    if sys.platform == "darwin":
-        MOUSE_BUTTONS = utils._bunch(
-            LEFT        = 1,
-            MIDDLE    = 3,
-            RIGHT        = 2);
-    else:
-        MOUSE_BUTTONS = utils._bunch(
-            LEFT        = 1,
-            MIDDLE    = 2,
-            RIGHT        = 3);
-
-    KEYCODES    = utils._bunch(
-        DELETE    = 46);
-
-    @staticmethod
-    def append_button(_window,text):
-        button = tk.Button(_window, text=text)
-        button.pack(fill=tk.BOTH, expand=1)
-        return ui.wrap_element(button)
-
-
-    @staticmethod
-    def append_canvas(_window,width,height,style):
-        canvas = tk.Canvas(_window,width=width,height=height)
-        canvas.config(**style)
-        canvas.pack(fill=tk.BOTH, expand=1)
-        return drawing.canvas_wrapper(canvas)
-
-
-    @staticmethod
-    def bind_event(source,event,controller,raise_name,port="ui"):
-        def __handle_event(ev=None):
-            #port="field_ui"
-            #source = "self.State[0].field_window"
-
-            if event == ui.EVENTS.KEY_PRESS :
-                #controller.addInput(Event(raise_name, port, [ev.keycode,source]))
-                ui.simulator.realtime_interrupt(f"{port} Event(self.{port},\"{raise_name}\",[{ev.keycode},{source}])")
-
-            elif event == ui.EVENTS.MOUSE_CLICK or \
-                  event == ui.EVENTS.MOUSE_MOVE or \
-                  event == ui.EVENTS.MOUSE_PRESS or \
-                  event == ui.EVENTS.MOUSE_RELEASE or \
-                    event == ui.EVENTS.MOUSE_RIGHT_CLICK :
-                
-           
-                ui.simulator.realtime_interrupt(f"{port} Event(\"{raise_name}\",self.{port},[{ev.x},{ev.y},\"{ev.num}\"])")
-                #controller.addInput(Event(raise_name, port, [ev.x, ev.y, ev.num]))
-
-            elif event == ui.EVENTS.WINDOW_CLOSE :
-                #TODO: Quick fix, use a better version of pypdevs because this one can only send strings. Be sure to not set any spaces in the second argument otherwise it
-                # does not register
-                #source = "self.State[0].field_window"
-
-                source = "list(self.instances)[0].field_window"
-                ui.simulator.realtime_interrupt(f"{port} Event(\"{raise_name}\",self.{port},[{source}])")
-                
-                #controller.addInput(Event(raise_name, port, [source]))
-
-            else:
-                raise Exception('Unsupported event');
-
-        if event == ui.EVENTS.WINDOW_CLOSE :
-            source.protocol(event, __handle_event)
-
-        elif issubclass(drawing.ui_element_wrapper,source.__class__) :
-            source.canvas_wrapper.element.tag_bind(source.element_id, event, __handle_event)
-
-        else :
-            source.bind(event, __handle_event)
-
-
-    @staticmethod
-    def close_window(_window):
-        _window.destroy()
-
-
-    @staticmethod
-    def log(value):
-        print(value)
-
-
-    @staticmethod
-    def new_window(width,height,title=None):
-        _window = tk.Toplevel(ui.window)
-        if title:
-            _window.title(title)
-        _window.geometry(str(width)+"x"+str(height)+"+300+300")
-        return _window
-
-
-    @staticmethod
-    def println(value,target):
-        raise Exception('Not implemented yet');
-
-
-    @staticmethod
-    def wrap_element(element):
-        return utils._bunch(element=element)
-

Разлика између датотеке није приказан због своје велике величине
+ 0 - 193
sccd/runtime/libs/DEVui_v2.py


+ 0 - 1
sccd/runtime/statecharts_core.py

@@ -266,7 +266,6 @@ class ObjectManagerBase(object):
             
             traversal_list = self.processAssociationReference(association_name)
             instances = self.getInstances(source, traversal_list)
-            # association = self.instances_map[source].getAssociation(traversal_list[0][0])
             association = source.associations[traversal_list[0][0]]
             
             for i in instances: