소스 검색

Added more background and methodology to thesis paper

sampieters 1 년 전
부모
커밋
2a3784c55e

+ 27 - 20
examples/FixedTimer/PyDEVS/runner.py

@@ -1,24 +1,31 @@
-from pypdevs.simulator import Simulator
-import target as target
+import tkinter as tk
+import examples.FixedTimer.PyDEVS.target as target
+from sccd.runtime.libs.ui_v2 import UI
+from sccd.runtime.DEVS_loop import DEVSSimulator
 
-from tkinter import *
-from sccd.runtime.libs.ui import ui
+class OutputListener:
+	def __init__(self, ui):
+		self.ui = ui
 
+	def add(self, event):
+		if event.port == "ui":
+			method = getattr(self.ui, event.name)
+			method(*event.parameters)
 
+if __name__ == '__main__':
+	model = target.Controller(name="controller")
+	refs = {"ui": model.ui, "field_ui": model.atomic0.field_ui}
+	
+	tkroot = tk.Tk()
+	tkroot.withdraw()
+	sim = DEVSSimulator(model)
+	sim.setRealTime(True)
+	sim.setRealTimeInputFile(None)
+	sim.setRealTimePorts(refs)
+	sim.setVerbose(None)
+	sim.setRealTimePlatformTk(tkroot)
 
-model = target.Controller(name="controller")
-#refs = {"ui": model.ui, "field_ui": model.atomic1.field_ui}
-ui.window = Tk()
-ui.window.withdraw()
-
-sim = Simulator(model)
-sim.setRealTime(True)
-sim.setRealTimeInputFile(None)
-#sim.setRealTimePorts(refs)
-sim.setVerbose(None)
-sim.setRealTimePlatformTk(ui.window)
-
-ui.simulator = sim
-
-sim.simulate()
-ui.window.mainloop()
+	ui = UI(tkroot, sim)
+	model.atomic0.addMyOwnOutputListener(OutputListener(ui))
+	sim.simulate()
+	tkroot.mainloop()

+ 147 - 43
examples/FixedTimer/PyDEVS/target.py

@@ -13,9 +13,8 @@ from pypdevs.simulator import *
 from sccd.runtime.libs.ui import ui
 from time import time
 
-CANVAS_WIDTH = 500
-CANVAS_HEIGHT = 250
-FONT_SIZE = 50
+CANVAS_WIDTH = 800
+CANVAS_HEIGHT = 550
 
 # package "Timer (Eventloop Version)"
 
@@ -33,59 +32,108 @@ class MainAppInstance(RuntimeClassBase):
         # build Statechart structure
         self.build_statechart_structure()
         
+        # user defined attributes
+        self.window_id = None
+        self.canvas_id = None
+        self.clock_id = None
+        self.actual_clock_id = None
+        self.button_id = None
+        
         # call user defined constructor
         MainAppInstance.user_defined_constructor(self)
+        self.inports["field_ui"] = ('field_ui', len(atomdevs.instances))
     
     def user_defined_constructor(self):
-        self.canvas = ui.append_canvas(ui.window,CANVAS_WIDTH,CANVAS_HEIGHT,{'background':'#222222'})
-        self.clock_text = self.canvas.element.create_text(
-            CANVAS_WIDTH / 2,
-            CANVAS_HEIGHT / 2,
-            text='0.0', 
-            anchor='center',
-            font=("TkDefaultFont", FONT_SIZE)
-            )
-        self.actual_clock_text = self.canvas.element.create_text(
-            CANVAS_WIDTH / 2, 
-            (CANVAS_HEIGHT / 2) + FONT_SIZE, 
-            text='0.0', 
-            anchor='center',
-            font=("TkDefaultFont", FONT_SIZE)
-        )
-        interrupt_button = ui.append_button(ui.window, 'INTERRUPT');
-        continue_button = ui.append_button(ui.window, 'CONTINUE');
-        #ui.bind_event(interrupt_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'interrupt_clicked');
-        #ui.bind_event(continue_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'continue_clicked');
+        pass
     
     def user_defined_destructor(self):
         pass
     
     
-    # user defined method
-    def update_timers(self):
-        self.canvas.element.itemconfigure(self.clock_text, text=str('%.2f' % (self.getSimulatedTime() / 1000.0)))
-        self.canvas.element.itemconfigure(self.actual_clock_text, text='%.2f' % (time() / 1000.0))
-    
-    
     # builds Statechart structure
     def build_statechart_structure(self):
         
         # state <root>
         self.states[""] = State(0, "", self)
         
+        # state /creating_window
+        self.states["/creating_window"] = State(1, "/creating_window", self)
+        self.states["/creating_window"].setEnter(self._creating_window_enter)
+        
+        # state /creating_canvas
+        self.states["/creating_canvas"] = State(2, "/creating_canvas", self)
+        self.states["/creating_canvas"].setEnter(self._creating_canvas_enter)
+        
+        # state /creating_clock_text
+        self.states["/creating_clock_text"] = State(3, "/creating_clock_text", self)
+        self.states["/creating_clock_text"].setEnter(self._creating_clock_text_enter)
+        
+        # state /creating_actual_clock_text
+        self.states["/creating_actual_clock_text"] = State(4, "/creating_actual_clock_text", self)
+        self.states["/creating_actual_clock_text"].setEnter(self._creating_actual_clock_text_enter)
+        
+        # state /creating_interrupt_button
+        self.states["/creating_interrupt_button"] = State(5, "/creating_interrupt_button", self)
+        self.states["/creating_interrupt_button"].setEnter(self._creating_interrupt_button_enter)
+        
+        # state /creating_resume_button
+        self.states["/creating_resume_button"] = State(6, "/creating_resume_button", self)
+        self.states["/creating_resume_button"].setEnter(self._creating_resume_button_enter)
+        
         # state /running
-        self.states["/running"] = State(1, "/running", self)
+        self.states["/running"] = State(7, "/running", self)
         self.states["/running"].setEnter(self._running_enter)
         self.states["/running"].setExit(self._running_exit)
         
         # state /interrupted
-        self.states["/interrupted"] = State(2, "/interrupted", self)
+        self.states["/interrupted"] = State(8, "/interrupted", self)
         
         # add children
+        self.states[""].addChild(self.states["/creating_window"])
+        self.states[""].addChild(self.states["/creating_canvas"])
+        self.states[""].addChild(self.states["/creating_clock_text"])
+        self.states[""].addChild(self.states["/creating_actual_clock_text"])
+        self.states[""].addChild(self.states["/creating_interrupt_button"])
+        self.states[""].addChild(self.states["/creating_resume_button"])
         self.states[""].addChild(self.states["/running"])
         self.states[""].addChild(self.states["/interrupted"])
         self.states[""].fixTree()
-        self.states[""].default_state = self.states["/running"]
+        self.states[""].default_state = self.states["/creating_window"]
+        
+        # transition /creating_window
+        _creating_window_0 = Transition(self, self.states["/creating_window"], [self.states["/creating_canvas"]])
+        _creating_window_0.setAction(self._creating_window_0_exec)
+        _creating_window_0.setTrigger(Event("window_created", None))
+        self.states["/creating_window"].addTransition(_creating_window_0)
+        
+        # transition /creating_canvas
+        _creating_canvas_0 = Transition(self, self.states["/creating_canvas"], [self.states["/creating_clock_text"]])
+        _creating_canvas_0.setAction(self._creating_canvas_0_exec)
+        _creating_canvas_0.setTrigger(Event("canvas_created", None))
+        self.states["/creating_canvas"].addTransition(_creating_canvas_0)
+        
+        # transition /creating_clock_text
+        _creating_clock_text_0 = Transition(self, self.states["/creating_clock_text"], [self.states["/creating_actual_clock_text"]])
+        _creating_clock_text_0.setAction(self._creating_clock_text_0_exec)
+        _creating_clock_text_0.setTrigger(Event("text_created", None))
+        self.states["/creating_clock_text"].addTransition(_creating_clock_text_0)
+        
+        # transition /creating_actual_clock_text
+        _creating_actual_clock_text_0 = Transition(self, self.states["/creating_actual_clock_text"], [self.states["/creating_interrupt_button"]])
+        _creating_actual_clock_text_0.setAction(self._creating_actual_clock_text_0_exec)
+        _creating_actual_clock_text_0.setTrigger(Event("text_created", None))
+        self.states["/creating_actual_clock_text"].addTransition(_creating_actual_clock_text_0)
+        
+        # transition /creating_interrupt_button
+        _creating_interrupt_button_0 = Transition(self, self.states["/creating_interrupt_button"], [self.states["/creating_resume_button"]])
+        _creating_interrupt_button_0.setTrigger(Event("button_created", None))
+        self.states["/creating_interrupt_button"].addTransition(_creating_interrupt_button_0)
+        
+        # transition /creating_resume_button
+        _creating_resume_button_0 = Transition(self, self.states["/creating_resume_button"], [self.states["/running"]])
+        _creating_resume_button_0.setAction(self._creating_resume_button_0_exec)
+        _creating_resume_button_0.setTrigger(Event("button_created", None))
+        self.states["/creating_resume_button"].addTransition(_creating_resume_button_0)
         
         # transition /running
         _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
@@ -107,14 +155,59 @@ class MainAppInstance(RuntimeClassBase):
         _interrupted_1.setTrigger(Event("continue_clicked", self.getInPortName("ui")))
         self.states["/interrupted"].addTransition(_interrupted_1)
     
+    def _creating_window_enter(self):
+        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [800, 600, "Fixed Timer", self.inports['field_ui']]))
+    
+    def _creating_canvas_enter(self):
+        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_WIDTH, CANVAS_HEIGHT, {'background':'#222222'}, self.inports['field_ui']]))
+    
+    def _creating_clock_text_enter(self):
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 50, '00:00', self.inports['field_ui']]))
+    
+    def _creating_actual_clock_text_enter(self):
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 100, '00:00', self.inports['field_ui']]))
+    
+    def _creating_interrupt_button_enter(self):
+        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, 'INTERRUPT', self.inports['field_ui']]))
+    
+    def _creating_resume_button_enter(self):
+        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, 'RESUME', self.inports['field_ui']]))
+    
     def _running_enter(self):
         self.addTimer(0, 0.05)
     
     def _running_exit(self):
         self.removeTimer(0)
     
+    def _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']]))
+    
+    def _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']]))
+    
+    def _creating_clock_text_0_exec(self, parameters):
+        text_id = parameters[0]
+        self.clock_id = text_id
+    
+    def _creating_actual_clock_text_0_exec(self, parameters):
+        text_id = parameters[0]
+        self.actual_clock_id = text_id
+    
+    def _creating_resume_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['field_ui']]))
+    
     def _running_0_exec(self, parameters):
-        self.update_timers()
+        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.clock_id, str('%.2f' % (self.getSimulatedTime() / 1000.0)), self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.actual_clock_id, str('%.2f' % (self.getSimulatedTime() / 1000.0)), self.inports['field_ui']]))
     
     def _running_1_exec(self, parameters):
         self.update_timers()
@@ -127,7 +220,7 @@ class MainAppInstance(RuntimeClassBase):
     
     def initializeStatechart(self):
         # enter default state
-        self.default_targets = self.states["/running"].getEffectiveTargetStates()
+        self.default_targets = self.states["/creating_window"].getEffectiveTargetStates()
         RuntimeClassBase.initializeStatechart(self)
 
 class MainApp(AtomicDEVS, ObjectManagerBase):
@@ -138,6 +231,7 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         self.name = "MainApp"
         self.obj_manager_out = self.addOutPort("obj_manager_out")
         self.outputs = {}
+        self.field_ui = self.addInPort("field_ui")
         self.obj_manager_in = self.addInPort("obj_manager_in")
         self.input = self.addInPort("input")
         self.instances.append(MainAppInstance(self))
@@ -147,6 +241,8 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
+        if self.field_ui in inputs:
+            all_inputs.extend(inputs[self.field_ui])
         if self.obj_manager_in in inputs:
             all_inputs.extend(inputs[self.obj_manager_in])
         if self.input in inputs:
@@ -169,11 +265,19 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
                 ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
                 self.to_send.append((input[0], input[1], ev))
             elif input[2].name == "delete_instance":
-                pass
-            elif input[2].name == "associate_instance":
-                pass
-            elif input[2].name == "disassociate_instance":
-                pass
+                for index in input[2].parameters[1]:
+                    i = self.instances[index]
+                    for assoc_name in i.associations:
+                        if not (assoc_name == "parent"):
+                            traversal_list = self.processAssociationReference(assoc_name)
+                            instances = self.getInstances(i["instance"], traversal_list)
+                            if len(instances) > 0:
+                                pass
+                    i.user_defined_destructor()
+                    i.stop()
+                self.instances = [self.instances[i] for i in range(len(self.instances)) if i not in input[2].parameters[1]]
+                ev = Event("instance_deleted", None, input[2].parameters[1], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
             elif input[2].name == "instance_created":
                 instance = self.instances[input[2].instance]
                 instance.addEvent(input[2])
@@ -181,11 +285,11 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
                 instance = self.instances[input[2].instance]
                 instance.addEvent(input[2])
             elif input[2].name == "instance_deleted":
-                pass
-            elif input[2].name == "instance_associated":
-                pass
-            elif input[2].name == "instance_disassociated":
-                pass
+                instance = self.instances[input[2].instance]
+                for association in instance.associations.items():
+                    if association[1].to_class == input[0]:
+                        for index in input[2].parameters:
+                            association[1].removeInstance(index)
             else:
                 ev = input[2]
                 self.addInput(ev)

+ 43 - 42
examples/FixedTimer/Python/target.py

@@ -33,7 +33,9 @@ class MainApp(RuntimeClassBase):
         # user defined attributes
         self.window_id = None
         self.canvas_id = None
-        self.text_id = None
+        self.clock_id = None
+        self.actual_clock_id = None
+        self.button_id = None
         
         # call user defined constructor
         MainApp.user_defined_constructor(self)
@@ -63,14 +65,14 @@ class MainApp(RuntimeClassBase):
         self.states["/creating_clock_text"] = State(3, "/creating_clock_text", self)
         self.states["/creating_clock_text"].setEnter(self._creating_clock_text_enter)
         
+        # state /creating_actual_clock_text
+        self.states["/creating_actual_clock_text"] = State(4, "/creating_actual_clock_text", self)
+        self.states["/creating_actual_clock_text"].setEnter(self._creating_actual_clock_text_enter)
+        
         # state /creating_interrupt_button
-        self.states["/creating_interrupt_button"] = State(4, "/creating_interrupt_button", self)
+        self.states["/creating_interrupt_button"] = State(5, "/creating_interrupt_button", self)
         self.states["/creating_interrupt_button"].setEnter(self._creating_interrupt_button_enter)
         
-        # state /creating_resume_button
-        self.states["/creating_resume_button"] = State(5, "/creating_resume_button", self)
-        self.states["/creating_resume_button"].setEnter(self._creating_resume_button_enter)
-        
         # state /running
         self.states["/running"] = State(6, "/running", self)
         self.states["/running"].setEnter(self._running_enter)
@@ -83,8 +85,8 @@ class MainApp(RuntimeClassBase):
         self.states[""].addChild(self.states["/creating_window"])
         self.states[""].addChild(self.states["/creating_canvas"])
         self.states[""].addChild(self.states["/creating_clock_text"])
+        self.states[""].addChild(self.states["/creating_actual_clock_text"])
         self.states[""].addChild(self.states["/creating_interrupt_button"])
-        self.states[""].addChild(self.states["/creating_resume_button"])
         self.states[""].addChild(self.states["/running"])
         self.states[""].addChild(self.states["/interrupted"])
         self.states[""].fixTree()
@@ -103,56 +105,48 @@ class MainApp(RuntimeClassBase):
         self.states["/creating_canvas"].addTransition(_creating_canvas_0)
         
         # transition /creating_clock_text
-        _creating_clock_text_0 = Transition(self, self.states["/creating_clock_text"], [self.states["/creating_interrupt_button"]])
+        _creating_clock_text_0 = Transition(self, self.states["/creating_clock_text"], [self.states["/creating_actual_clock_text"]])
         _creating_clock_text_0.setAction(self._creating_clock_text_0_exec)
         _creating_clock_text_0.setTrigger(Event("text_created", None))
         self.states["/creating_clock_text"].addTransition(_creating_clock_text_0)
         
+        # transition /creating_actual_clock_text
+        _creating_actual_clock_text_0 = Transition(self, self.states["/creating_actual_clock_text"], [self.states["/creating_interrupt_button"]])
+        _creating_actual_clock_text_0.setAction(self._creating_actual_clock_text_0_exec)
+        _creating_actual_clock_text_0.setTrigger(Event("text_created", None))
+        self.states["/creating_actual_clock_text"].addTransition(_creating_actual_clock_text_0)
+        
         # transition /creating_interrupt_button
-        _creating_interrupt_button_0 = Transition(self, self.states["/creating_interrupt_button"], [self.states["/creating_resume_button"]])
+        _creating_interrupt_button_0 = Transition(self, self.states["/creating_interrupt_button"], [self.states["/running"]])
+        _creating_interrupt_button_0.setAction(self._creating_interrupt_button_0_exec)
         _creating_interrupt_button_0.setTrigger(Event("button_created", None))
         self.states["/creating_interrupt_button"].addTransition(_creating_interrupt_button_0)
         
-        # transition /creating_resume_button
-        _creating_resume_button_0 = Transition(self, self.states["/creating_resume_button"], [self.states["/running"]])
-        _creating_resume_button_0.setTrigger(Event("button_created", None))
-        self.states["/creating_resume_button"].addTransition(_creating_resume_button_0)
-        
         # transition /running
         _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
         _running_0.setAction(self._running_0_exec)
         _running_0.setTrigger(Event("_0after"))
         self.states["/running"].addTransition(_running_0)
         _running_1 = Transition(self, self.states["/running"], [self.states["/interrupted"]])
-        _running_1.setAction(self._running_1_exec)
-        _running_1.setTrigger(Event("interrupt_clicked", self.getInPortName("ui")))
+        _running_1.setTrigger(Event("mouse_click", self.getInPortName("button_ui")))
+        _running_1.setGuard(self._running_1_guard)
         self.states["/running"].addTransition(_running_1)
-        
-        # transition /interrupted
-        _interrupted_0 = Transition(self, self.states["/interrupted"], [self.states["/interrupted"]])
-        _interrupted_0.setAction(self._interrupted_0_exec)
-        _interrupted_0.setTrigger(Event("interrupt_clicked", self.getInPortName("ui")))
-        self.states["/interrupted"].addTransition(_interrupted_0)
-        _interrupted_1 = Transition(self, self.states["/interrupted"], [self.states["/running"]])
-        _interrupted_1.setAction(self._interrupted_1_exec)
-        _interrupted_1.setTrigger(Event("continue_clicked", self.getInPortName("ui")))
-        self.states["/interrupted"].addTransition(_interrupted_1)
     
     def _creating_window_enter(self):
-        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [800, 600, "Fixed Timer", self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [CANVAS_WIDTH, CANVAS_HEIGHT, "Fixed Timer", self.inports['field_ui']]))
     
     def _creating_canvas_enter(self):
-        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_WIDTH, CANVAS_HEIGHT, {'background':'#222222'}, self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_WIDTH, CANVAS_HEIGHT - 200, {'background':'#222222'}, self.inports['field_ui']]))
     
     def _creating_clock_text_enter(self):
-        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 50, '00:00', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 50, '', self.inports['field_ui']]))
+    
+    def _creating_actual_clock_text_enter(self):
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, 50, 100, '', self.inports['field_ui']]))
     
     def _creating_interrupt_button_enter(self):
         self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, 'INTERRUPT', self.inports['field_ui']]))
     
-    def _creating_resume_button_enter(self):
-        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, 'RESUME', self.inports['field_ui']]))
-    
     def _running_enter(self):
         self.addTimer(0, 0.05)
     
@@ -174,19 +168,26 @@ class MainApp(RuntimeClassBase):
     
     def _creating_clock_text_0_exec(self, parameters):
         text_id = parameters[0]
-        self.text_id = text_id
-    
-    def _running_0_exec(self, parameters):
-        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.text_id, str('%.2f' % (self.getSimulatedTime() / 1000.0)), self.inports['field_ui']]))
+        self.clock_id = text_id
     
-    def _running_1_exec(self, parameters):
-        self.update_timers()
+    def _creating_actual_clock_text_0_exec(self, parameters):
+        text_id = parameters[0]
+        self.actual_clock_id = text_id
     
-    def _interrupted_0_exec(self, parameters):
-        self.update_timers()
+    def _creating_interrupt_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['field_ui']]))
     
-    def _interrupted_1_exec(self, parameters):
-        self.update_timers()
+    def _running_0_exec(self, parameters):
+        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.clock_id, str('%.2f' % (self.getSimulatedTime() / 1000.0)), self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("update_text", self.getOutPortName("ui"), [self.canvas_id, self.actual_clock_id, str('%.2f' % (self.getSimulatedTime() / 1000.0)), self.inports['field_ui']]))
+    
+    def _running_1_guard(self, parameters):
+        x = parameters[0]
+        y = parameters[1]
+        button = parameters[2]
+        return button == ui.MOUSE_BUTTONS.LEFT
     
     def initializeStatechart(self):
         # enter default state

+ 44 - 31
examples/FixedTimer/sccd.xml

@@ -13,14 +13,16 @@
     <class name="MainApp" default="true">
         <attribute name="window_id" />
         <attribute name="canvas_id" />
-        <attribute name="text_id" />
+        <attribute name="clock_id" />
+        <attribute name="actual_clock_id" />
+        <attribute name="button_id" />
         <inport name="field_ui"/>
         <scxml initial="creating_window">
             <state id="creating_window">
                 <onentry>
                     <raise port="ui" event="create_window">
-                        <parameter expr="800"/><!-- width -->
-                        <parameter expr="600"/><!-- height -->
+                        <parameter expr="CANVAS_WIDTH"/><!-- width -->
+                        <parameter expr="CANVAS_HEIGHT"/><!-- height -->
                         <parameter expr='"Fixed Timer"'/><!-- title -->
                         <parameter expr="self.inports['field_ui']"/><!-- inport for response -->
                     </raise>
@@ -51,7 +53,7 @@
                     <raise port="ui" event="create_canvas">
                         <parameter expr="self.window_id"/><!-- window_id -->
                         <parameter expr="CANVAS_WIDTH"/><!-- width -->
-                        <parameter expr="CANVAS_HEIGHT"/><!-- height -->
+                        <parameter expr="CANVAS_HEIGHT - 200"/><!-- height -->
                         <parameter expr="{'background':'#222222'}"/><!-- style -->
                         <parameter expr="self.inports['field_ui']"/><!-- inport for response -->
                     </raise>
@@ -89,67 +91,78 @@
                         <parameter expr="self.canvas_id" />
                         <parameter expr="50" />
                         <parameter expr="50" />
-                        <parameter expr="'00:00'" />
+                        <parameter expr="''" />
                         <parameter expr="self.inports['field_ui']" />
                     </raise>
                 </onentry>
-                <transition event="text_created" target="../creating_interrupt_button">
+                <transition event="text_created" target="../creating_actual_clock_text">
                     <parameter name="text_id" type="int" />
                     <script>
-                        <![CDATA[
-                        self.text_id = text_id
-                        ]]>
+                        self.clock_id = text_id
                     </script>
                 </transition>
             </state>
-            <state id="creating_interrupt_button">
+            <state id="creating_actual_clock_text">
                 <onentry>
-                    <raise port="ui" event="create_button">
-                        <parameter expr="self.window_id" />
-                        <parameter expr="'INTERRUPT'" />
+                    <raise port="ui" event="create_text">
+                        <parameter expr="self.canvas_id" />
+                        <parameter expr="50" />
+                        <parameter expr="100" />
+                        <parameter expr="''" />
                         <parameter expr="self.inports['field_ui']" />
                     </raise>
                 </onentry>
-                <transition event="button_created" target="../creating_resume_button">
+                <transition event="text_created" target="../creating_interrupt_button">
+                    <parameter name="text_id" type="int" />
+                    <script>
+                        self.actual_clock_id = text_id
+                    </script>
                 </transition>
             </state>
-            <state id="creating_resume_button">
+            <state id="creating_interrupt_button">
                 <onentry>
                     <raise port="ui" event="create_button">
                         <parameter expr="self.window_id" />
-                        <parameter expr="'RESUME'" />
+                        <parameter expr="'INTERRUPT'" />
                         <parameter expr="self.inports['field_ui']" />
                     </raise>
                 </onentry>
                 <transition event="button_created" target="../running">
+                    <parameter name="button_id" type="int"/>
+                    <script>
+                        self.button_id = button_id
+                    </script> 
+                    <raise port="ui" event="bind_event">
+                        <parameter expr="button_id"/><!-- widget_id -->
+                        <parameter expr="ui.EVENTS.MOUSE_CLICK"/><!-- tk_event -->
+                        <parameter expr='"mouse_click"'/><!-- sccd_event_name -->
+                        <parameter expr="self.inports['field_ui']"/><!-- inport for response -->
+                    </raise>
                 </transition>
             </state>
             <state id="running">
                 <transition target="." after="0.05">
                     <raise port="ui" event="update_text">
                         <parameter expr="self.canvas_id" />
-                        <parameter expr="self.text_id" />
+                        <parameter expr="self.clock_id" />
+                        <parameter expr="str('%.2f' % (self.getSimulatedTime() / 1000.0))" />
+                        <parameter expr="self.inports['field_ui']" />
+                    </raise>
+                    <raise port="ui" event="update_text">
+                        <parameter expr="self.canvas_id" />
+                        <parameter expr="self.actual_clock_id" />
                         <parameter expr="str('%.2f' % (self.getSimulatedTime() / 1000.0))" />
                         <parameter expr="self.inports['field_ui']" />
                     </raise>
                 </transition>
-                <transition target="../interrupted" event="interrupt_clicked" port="ui">
-                    <script>
-                        self.update_timers()
-                    </script>
+                <transition port='button_ui' event="mouse_click" target='../interrupted' cond="button == ui.MOUSE_BUTTONS.LEFT">
+                    <parameter name="x" />
+                    <parameter name="y" />
+                    <parameter name="button" />
                 </transition>
             </state>
             <state id="interrupted">
-                <transition target="." event="interrupt_clicked" port="ui">
-                    <script>
-                        self.update_timers()
-                    </script>
-                </transition>
-                <transition target="../running" event="continue_clicked" port="ui">
-                    <script>
-                        self.update_timers()
-                    </script>
-                </transition>
+
             </state>
         </scxml>
     </class>

+ 195 - 5
paper/02-Background.tex

@@ -1,9 +1,178 @@
 \chapter{Background}
 \label{chapt:Background}
 
-\section{SCCD}
-\subsection{Statechart}
-\subsection{SCXML}
+\section{Statecharts and Class Diagrams (SCCD)}
+\subsection{The Statechart Formalism}
+
+\subsection{State Chart XML (SCXML)}
+State Chart XML (SCXML) is a general-purpose event-based state machine language that combines concepts from CCXML and Harel 
+State Tables. 
+
+
+
+
+\subsection{Statecharts and Class Diagrams (SCCD)}
+In this section the SCCD (a Statecharts and Class Diagrams hybrid) formalism and its SCCDXML representation, an extension 
+of SCXML, is explained. SCCD facilitates the specification of complex timed, reactive, interactive discrete-event systems 
+(e.g., complex user interfaces).
+
+\subsubsection{The SCCD language}
+The SCCD languages extends the SCXML, explained in subsection (TODO), by adding new features to its concrete syntax.
+
+\paragraph{Top-level Elements}
+The top-level element is a diagram. It has an input/output interface to communicate with its environment, it can optionally 
+import library classes, and it holds a number of class definitions. One of these classes is the default, and is instantiated 
+when the application is launched.
+
+% TODO: Listing
+
+Listing (TODO) shows the top-level diagram of an application. It imports a library class that is used to draw the graphical 
+elements on the screen, one input port called "input" which receives events when the user interacts with the UI (for example, 
+pressing a key), and four classes, explained in the following subsections.
+
+\paragraph{Classes}
+Classes are the main addition of the SCCD language. They model both structure and behaviour—structure in the form of 
+attributes and relations with other classes, behaviour in the form of methods, which access and change the values of 
+attributes of the class, and an SCXML model, which constitutes the "modal" part of the system, modelling the control flow 
+of the class's behaviour. At runtime, a class can be instantiated, which creates an object. Objects are initialized according 
+to the class's constructor, and can be deleted, invoking the class's destructor. The relationships modelled between classes 
+are instantiated at runtime in the form of links. They serve as communication channels, over which objects can send and receive 
+events.
+
+% TODO: Listing
+
+Listing 2 shows the definition of the "Ball" class. It defines a number of relations (discussed in the next paragraph), a 
+constructor and destructor, a method that moves the ball to a new position, and an SCXML model that consists of four states. 
+It can optionally also define private input ports and output ports. In this case, the ball defines a private input port, that 
+allows the environment to send events that are only meant for a particular ball. For example, when the user left-clicks on a 
+ball to select it, that event should only be sent to that specific instance.
+
+\paragraph{Relationships}
+Classes can have relationships with other classes. There are two types of relationships: associations and inheritance.
+
+An association is defined between a source class and a target class, and has a name. It allows instances of the source class 
+to send events to instances of the target class by referencing the association name. An association has a multiplicity, 
+defined as a minimal cardinality $c_{min} \in \mathbb{N}$ and a maximal cardinality $c_{max} \in \mathbb{N}_{>0} \cup \{inf\}$. 
+They control how many instances of the target class have to be minimally associated to each instance of the source class, and 
+how many instances of the target class can be maximally associated to each instance of the source class, respectively. Each 
+time an association is created, it results in a link between the source and target object. This link gets a unique identifier, 
+allowing the source object to reference the target, for example to send events.
+
+An inheritance relation results in the source of the relation to inherit all attributes and methods from the target of the 
+relation. Specialisation of modal behaviour (i.e., (parts of) the SCXML model of the superclass) is currently not supported.
+
+% TODO: Listing
+
+Listing (TODO) shows the relationships of the "Window" class. It has an association to its parent, the main application. 
+Exactly one instance of that link has to exist between each "Window" instance and the main application. It is additionally 
+associated to a number of buttons and balls, and inherits from the library class "UIWidget", allowing it to be drawn on screen.
+
+\paragraph{Events}
+Events in SCCD are strings. They are accompanied by a number of parameter values: the sender is obliged to send the correct 
+number of values, and the receiver declares the parameters when catching the event. Each parameter has a name, that can be used 
+as a local variable in the action associated with the transition that catches the event.
+
+With the addition of a public input/output interface using ports, as well as classes and associations, comes the need for 
+scoping events. In traditional SCXML models, an event is sensed by the Statecharts model that generated it. SCCD adds the ability 
+to transmit events to class instances and to output ports. In particular, the raise tag was extended with a scope attribute, that 
+can take on the following values:
+\begin{itemize}
+    \item \textbf{local:} The event will only be visible for the sending instance.
+    \item \textbf{broad:} The event is broadcast to all instances.
+    \item \textbf{output:} The event is sent to an output port and is only valid in combination with the output attribute, which 
+    specifies the name of the output port.
+    \item \textbf{narrow:} The event is narrow-cast to specific instances only, and is only valid in combination with the target 
+    attribute, which specifies the instance to send the event to. For example, an instance of the "Window" class can narrow-cast 
+    an event by sending the event to a specific instance of the "Ball" class, identified by a unique link identifier.
+    \item \textbf{cd:} The event is processed by the object manager. See the next section for more details.
+\end{itemize}
+% TODO: Listing 
+Listing (TODO) presents a transition modelled on the "Button" class. It reacts to the user left-clicking the button (represented 
+by an event sent on the button input port). The button reacts by notifying its parent that it was clicked.
+
+\subsubsection{The Object Manager}
+At runtime, a central entity called the object manager is responsible for creating, deleting, and starting class instances, as 
+well as managing links (instances of associations) between class instances. It also checks whether no cardinalities are violated: 
+when the user creates an association, it checks that the maximal cardinality is not violated, and when the user deletes an 
+association, it check whether the minimal cardinality is not violated. As mentioned previously, instances can send events to the 
+object manager using the "cd" scope. The object manager can thus be seen as an ever-present, globally accessible object instance, 
+although it is implicitly defined in the runtime, instead of as a SCCD class.
+
+When the application is started, the object manager creates an instance of the default class and starts its associated Statecharts 
+model. From then on, instances can send several events to the object manager to control the set of currently executing objects. 
+The object manager accepts four events. We list them below, including the parameters that have to be sent as part of the event:
+\begin{itemize}
+    \item \textbf{create\_instance(association name, class name, args*):}
+    \item \textbf{delete\_instance(link\_ref):}
+    \item \textbf{start\_instance(link\_ref):}
+    \item \textbf{associate\_instance(source\_ref, association\_name, target\_ref):}
+\end{itemize}
+
+% TODO: Verder aanvullen
+
+\subsubsection{The SCCD compiler}
+The semantics of an SCCD model are loosely based on the agent model, where each instance of a class can be seen as an agent that 
+communicates with other agents through its input/output interface, and its autonomous behaviour controlled by its Statecharts 
+model. The compiler generates appropriate code that continuously executes the system by allowing each agent to execute a step, 
+which optionally generates output that can be sensed by the other agents.
+
+The compiler supports two programming languages, Javascript and Python, and options for the statecharts semantics. Supporting 
+multiple languages is a major advantage, as one can imagine developing an application in SCCD and generating code for multiple 
+languages from the same model. The generated code would exhibit identical behaviour for each implementation language, such as a 
+web-based application (implemented in HTML/Javascript) and a desktop application (implemented in, for example, Python).
+
+SCCD has one semantic definition. There are, however, many platforms on which the code generated from an SCCD model can be run. 
+The runtime platform provides essential functions used by the runtime kernel, such as the queueing of events and the scheduling 
+of (timed) events. Three runtime platforms are supported. A platform holds a list (or queue) of events, and they differ in the 
+way they handle events generated during execution. The kernel attempts to run the SCCD model in real-time, meaning that the delay 
+on timed transitions is intepreted as an amount of seconds. Raising of events and untimed transitions are executed as fast as 
+possible. Figure (TODO) presents an overview of the three platforms, and how they handle events.
+
+The most basic platform, available in most programming languages, is based on threads. Currently, the platform runs one thread, 
+which manipulates a global event queue, made thread-safe by locks. Input from the environment is handled by obtaining this lock, 
+which the kernel releases after every step of the execution algorithm. This allows external input to be interleaved with 
+internally raised events. Running an application on this platform can interfere with other scheduling mechanisms, such as a UI 
+module, however.
+
+To overcome this interference problem, the event loop platform reuses the event queue managed by an existing UI platform, such 
+as Tkinter. The UI platform provides functions for managing time-outs (for timed events), as well as pushing and popping items 
+from the queue. This results in a seamless integration of both Statecharts events and external UI events, such as user clicks: 
+the UI platform is now responsible for the correct interleaving.
+
+The game loop platform facilitates integration with game engines (such as the open-source Unity engine), where objects are 
+updated only at predefined points in time. In the "update" function, the kernel is responsible for checking the current time 
+(as some time has passed since the last call to the "up-date" function), and process all the events generated by objects. This 
+means that events generated in between two of these points are not processed immediately, but queued and their processing delayed 
+until the next processing time.
+
+\subsubsection{Semantics}
+The Statecharts language has been around for a long time. In that time, its basic structures have almost not changed. In its 
+original definition [(TODO)], Harel left many of the semantic choices undefined. Since then, many semantics have been defined, 
+such as the one used in Statemate [(TODO)]. More recently, Esmaeilsabzali et al. [(TODO)] have performed a study of big-step 
+modelling languages, such as Statecharts, and defined a set of semantic variation points, with which the different Statecharts 
+execution semantics can be classified. Central to their discussion is the notion of a "big step". The execution of a Statecharts 
+model is a sequence of big steps. A big step is a unit of interaction between a model and its environment. A big step takes input 
+from the environment (at the beginning of the big step), and produces output to the environment (after the big step has taken 
+place). Input cannot change during the big step. A big step consists of 0 or more small steps. A small step is an unordered set 
+of 1 or more transition executions, but in our case, a small step always consists of exactly one transition execution. Small steps 
+are grouped in so-called combo steps. A combo step is a maximal sequence of small steps, such that it only contains transitions 
+that are orthogonal to each other.
+
+The SCCD compiler allows to choose which semantics to use based on a number of semantic variation points. This gives modellers 
+more control to fine-tune the application to their needs. The semantic variation points are:
+\begin{itemize}
+    \item \textbf{Big Step Maximality} specifies when a big step ends: either after one combo step executed (Take One), or when 
+    no more combo steps can be executed (Take Many).
+    \item \textbf{Internal Event Lifeline} specifies when an internally raised event becomes available: either in the next small 
+    step (immediately), in the next combo step (which only makes sense in combination with the Take Many option), or the event is 
+    queued and treated as an external event (making it available in the next big step).
+    \item \textbf{Input Event Lifeline} specifies when an input event is available during a big step: either throughout the first 
+    small step, the first combo step, or throughout the whole big step.
+    \item \textbf{Priority} specifies what to do when two transitions are enabled at the same time, where the source state of one 
+    of the transitions is the ancestor of the source state of the other transition. Either the transition of the ancestor gets 
+    priority (Source-Parent), or the transition of the (indirect) child gets priority (Source-Child).
+\end{itemize}
+
 
 \section{DEVS Formalism}
 The Discrete Event System Specification (DEVS)
@@ -328,7 +497,7 @@ that allows hierarchical DEVS models to be easily defined. The simulation engine
 of both the model architecture and the SE follows.
 
 \subsubsection{Model Architecture}
-The model architecture implemented in DEVS.py is a canvas from which hierarchical DEVS mod- els can be easily described. It consists 
+The model architecture implemented in DEVS.py is a canvas from which hierarchical DEVS models can be easily described. It consists 
 of a number of classes arranged to capture the essence of hierarchical DEVS. A model is described in a dedicated file by deriving 
 coupled and/or atomic- DEVS descriptive classes from this architecture. These atomic models are then arranged hierarchically through 
 composition. Methods and attributes form the standard interface that allows an SE, such as the one described in the next sub-section, 
@@ -374,4 +543,25 @@ Coupling of ports is performed through the connectPorts method. Its first parame
 destination port. A coupling is rejected and an error message issued if the coupling is invalid.
 
 The source and destination ports are instances of the class Port. This class defines channels where events may pass between DEVS models. 
-These channels are defined in the Port's inLine and outLine attributes.
+These channels are defined in the Port's inLine and outLine attributes.
+
+Consider the example of the situation illustrated in Figure (TODO). There exists a descriptive class SomeDEVS for a DEVS (either atomic 
+or coupled) with an input and output port locally known as IN and OUT. We want to connect the input port to the output port of the 
+SimpleGenerator atomic- DEVS described above: both DEVS must of course be children of the same coupled-DEVS for the coupling to be 
+performed. The coupled-DEVS descriptive class is defined below.
+
+% TODO: code
+
+Note that the parameter to the constructor is used to parameterize the SimpleGenerator atomic- DEVS. As for atomic-DEVS, the constructor 
+first calls the parent class' constructor. Note also that the coupled-DEVS itself has an output port. The first coupling is an internal 
+coupling, while the second is an external output coupling. This is a complete definition for a coupled-DEVS descriptive class. The 
+default select function is used.
+
+Once all the descriptive classes in the hierarchical DEVS model have been defined, the whole model can be build by instantiating the 
+root DEVS. This is possible since the hierarchical representation of the model is built by composition rather than aggregation.
+
+As a final warning, note that recursive definitions are illegal, since they are incompatible with a tree structure. As a trivial example, 
+a coupled-DEVS' descriptive class SomeCoupledDEVS cannot call in its constructor the addSubModel method with an instance of 
+SomeCoupledDEVS. This is mentionned since such recursive constructs will not be detected.
+
+\subsubsection{Simulation Engine}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 16 - 21
paper/03-Methodology.tex


+ 11 - 11
paper/MasterThesis.fdb_latexmk

@@ -1,13 +1,13 @@
 # Fdb version 3
-["bibtex MasterThesis"] 0 "MasterThesis.aux" "MasterThesis.bbl" "MasterThesis" 1714397675
+["bibtex MasterThesis"] 0 "MasterThesis.aux" "MasterThesis.bbl" "MasterThesis" 1714676905
   "/usr/local/texlive/2019/texmf-dist/bibtex/bst/base/plain.bst" 1292289607 20613 bd3fbfa9f64872b81ac57a0dd2ed855f ""
   "MasterThesis.aux" 0 -1 0 "pdflatex"
   "references.bib" 1312367667 789 20803d158fccdc749b2e64f161e2607a ""
   (generated)
   "MasterThesis.bbl"
   "MasterThesis.blg"
-["pdflatex"] 1714397674 "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.tex" "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.pdf" "MasterThesis" 1714397675
-  "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.aux" 1714397674 8 a94a2480d3289e625eea47cd1b285758 ""
+["pdflatex"] 1714676904 "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.tex" "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.pdf" "MasterThesis" 1714676905
+  "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.aux" 1714676904 8 a94a2480d3289e625eea47cd1b285758 ""
   "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.tex" 1708595575 2030 b07d38d40f55a12ddbb2150cd1cb0161 ""
   "/usr/local/texlive/2019/texmf-dist/fonts/map/fontname/texfonts.map" 1511824771 3332 103109f5612ad95229751940c61aada0 ""
   "/usr/local/texlive/2019/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm" 1136768653 1324 c910af8c371558dc20f2d7822f66fe64 ""
@@ -96,8 +96,8 @@
   "00-Acknowledgements.tex" 1714059530 667 8e107c839354f000e37d04dc25ae918a ""
   "00-NedSamenvatting.tex" 1312367667 167 8399376b625bface729d36e4e2250554 ""
   "01-Introduction.tex" 1714128909 4068 1b7abf65cd933cb114e95a696e069d8b ""
-  "02-Background.tex" 1714397673 24621 e803b54ac801b9deb14b541ef1e967bd ""
-  "03-Methodology.tex" 1708865037 5239 30d99e6e522d5663924569fc8bdf8d22 ""
+  "02-Background.tex" 1714676904 39831 bbf7f9c5419941500454d3c612587104 ""
+  "03-Methodology.tex" 1714671440 3007 85ab628e3d6b6fd066fda64108846d3b ""
   "04-Implementation.tex" 1708595418 112 55cb6455e2f9f0104ec4d8e6d0f49273 ""
   "05-Examples.tex" 1708595429 100 9e94dd9a3549d797588d04c14167759b ""
   "99-Conclusions.tex" 1312367667 96 14738e95e1c9f65e878257a213a68c0e ""
@@ -117,12 +117,12 @@
   "picinpar.sty" 1312367667 24409 c0cc078f3063909ee9f34b5dc9ae71ef ""
   "titlesec.sty" 1312367667 47627 5593f18067f6da9a34ba2dc08abaee8e ""
   (generated)
-  "MasterThesis.out"
-  "MasterThesis.log"
   "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.log"
-  "MasterThesis.lof"
-  "MasterThesis.aux"
-  "MasterThesis.toc"
   "/Users/sampieters/Desktop/VSCodeProjects/SCCD2DEVS/paper/MasterThesis.pdf"
-  "MasterThesis.pdf"
   "MasterThesis.lot"
+  "MasterThesis.log"
+  "MasterThesis.pdf"
+  "MasterThesis.out"
+  "MasterThesis.toc"
+  "MasterThesis.aux"
+  "MasterThesis.lof"

BIN
paper/MasterThesis.pdf


BIN
paper/MasterThesis.synctex.gz