Jelajahi Sumber

Fully modelled traffic light

Yentl Van Tendeloo 8 tahun lalu
induk
melakukan
bc38801f3a
3 mengubah file dengan 302 tambahan dan 50 penghapusan
  1. 3 0
      models/SCCD.mvc
  2. 34 29
      models/SCCD_execute.alc
  3. 265 21
      models/dynamic_trafficlight.mvc

+ 3 - 0
models/SCCD.mvc

@@ -57,6 +57,9 @@ Class BasicState : State{
     onExitScript? : Action
 }
 
+Association onEntryRaise (BasicState, Raise) {}
+Association onExitRaise (BasicState, Raise) {}
+
 Association behaviour(Class, BasicState){
     target_lower_cardinality = 1
     target_upper_cardinality = 1

+ 34 - 29
models/SCCD_execute.alc

@@ -269,6 +269,39 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 		action(class_data["attributes"])
 	return!
 
+Void function process_raised_event(model : Element, event : Element, parameter_action : Element, data : Element):
+	String scope
+	scope = read_attribute(model, event, "scope")
+	if (scope == "cd"):
+		// Is an event for us internally, so don't append
+		// Instead, we process it directly
+		String operation
+		operation = read_attribute(model, event, "event")
+		if (operation == "create_instance"):
+			// Start up a new class of the desired type
+
+			// Parameters of this call:
+			// class -- type of the class to instantiate
+			// identifier -- name of this instance, for future reference
+			// parameters -- parameters for constructor
+			String class
+			String identifier
+			Element parameters
+			class = set_pop(filter(model, allInstances(model, "SCCD/Class"), "name", list_read(parameter_action, 0)))
+			identifier = list_read(parameter_action, 1)
+			parameters = list_read(parameter_action, 2)
+			start_class(model, data, class, identifier, parameters)
+
+		elif (operation == "delete_instance"):
+			// Delete the requested class
+			String identifier
+			identifier = list_read(parameter_action, 0)
+			delete_class(model, data, identifier)
+	else:
+		set_add(data["events"], create_tuple(read_attribute(model, event, "event"), parameter_action))
+
+	return !
+
 Element function execute_transition(model : Element, data : Element, class : String, transition_tuple : Element):
 	// Execute the script (if any)
 	Element script
@@ -296,35 +329,7 @@ Element function execute_transition(model : Element, data : Element, class : Str
 			parameter_action = get_func_AL_model(import_node(parameter_action))
 			parameter_action = parameter_action(data["classes"][class]["attributes"], event_parameter)
 
-		String scope
-		scope = read_attribute(model, event, "scope")
-		if (scope == "cd"):
-			// Is an event for us internally, so don't append
-			// Instead, we process it directly
-			String operation
-			operation = read_attribute(model, event, "event")
-			if (operation == "create_instance"):
-				// Start up a new class of the desired type
-
-				// Parameters of this call:
-				// class -- type of the class to instantiate
-				// identifier -- name of this instance, for future reference
-				// parameters -- parameters for constructor
-				String class
-				String identifier
-				Element parameters
-				class = set_pop(filter(model, allInstances(model, "SCCD/Class"), "name", list_read(parameter_action, 0)))
-				identifier = list_read(parameter_action, 1)
-				parameters = list_read(parameter_action, 2)
-				start_class(model, data, class, identifier, parameters)
-
-			elif (operation == "delete_instance"):
-				// Delete the requested class
-				String identifier
-				identifier = list_read(parameter_action, 0)
-				delete_class(model, data, identifier)
-		else:
-			set_add(data["events"], create_tuple(read_attribute(model, event, "event"), parameter_action))
+		process_raised_event(model, event, parameter_action, data)
 
 	// Find new set of states
 	Element target_states

+ 265 - 21
models/dynamic_trafficlight.mvc

@@ -14,17 +14,17 @@ Class manager {
                 return !
         $
 
-    {behaviour} CompositeState manager_root {
-        name = "root"
+    {behaviour} CompositeState manager_main {
+        name = "main"
         isInitial = True
-        {composite_children} BasicState manager_root_start {
+        {composite_children} BasicState manager_main_start {
             name = "start"
             isInitial = True
         }
     }
 }
 
-transition (manager_root_start, manager_root_start) {
+transition (manager_main_start, manager_main_start) {
     name = "create"
     event = "create"
 
@@ -44,7 +44,7 @@ transition (manager_root_start, manager_root_start) {
     }
 }
 
-transition (manager_root_start, manager_root_start) {
+transition (manager_main_start, manager_main_start) {
     name = "delete"
     event = "delete"
 
@@ -67,76 +67,320 @@ Class trafficlight {
     constructor_body = $
             Void function constructor(attributes : Element, parameters : Element):
                 dict_add(attributes, "counter", 0)
+                dict_add(attributes, "colour", "")
                 return!
         $
 
-    {behaviour} CompositeState trafficlight_root {
-        name = "root"
+    {behaviour} CompositeState trafficlight_main {
+        name = "main"
         isInitial = True
-        {composite_children} BasicState trafficlight_root_off {
+        {composite_children} BasicState trafficlight_main_off {
             name = "off"
             isInitial = True
         }
 
-        {composite_children} ParallelState trafficlight_root_main {
+        {composite_children} ParallelState trafficlight_main_main {
             name = "main"
             isInitial = False
 
-            {parallel_children} CompositeState trafficlight_root_main_trafficlight {
+            {onExitRaise} Raise {
+                event = "displayNone"
+            }
+
+            {parallel_children} CompositeState trafficlight_main_main_trafficlight {
                 name = "trafficlight"
                 isInitial = False
 
-                {composite_children} CompositeState trafficlight_root_main_trafficlight_normal {
+                {composite_children} CompositeState trafficlight_main_main_trafficlight_normal {
                     name = "normal"
                     isInitial = True
 
-                    {composite_children} BasicState trafficlight_root_main_trafficlight_normal_red {
+                    onExitScript = $
+                            Void function onexit(attributes : Element):
+                                dict_overwrite(attributes, "colour", "")
+                                return!
+                        $
+
+                    {composite_children} BasicState trafficlight_main_main_trafficlight_normal_red {
                         name = "red"
                         isInitial = True
+
+                        onEntryScript = $
+                                Void function onentry(attributes : Element):
+                                    dict_overwrite(attributes, "counter", 60)
+                                    dict_overwrite(attributes, "colour", "red")
+                                    return!
+                            $
+
+                        {onEntryRaise} Raise {
+                            event = "displayRed"
+                        }
+                        {onEntryRaise} Raise {
+                            event = "resetTimer"
+                        }
                     }
 
-                    {composite_children} BasicState trafficlight_root_main_trafficlight_normal_green {
+                    {composite_children} BasicState trafficlight_main_main_trafficlight_normal_green {
                         name = "green"
                         isInitial = False
+
+                        onEntryScript = $
+                                Void function onentry(attributes : Element):
+                                    dict_overwrite(attributes, "counter", 55)
+                                    dict_overwrite(attributes, "colour", "green")
+                                    return!
+                            $
+
+                        {onEntryRaise} Raise {
+                            event = "displayGreen"
+                        }
+                        {onEntryRaise} Raise {
+                            event = "resetTimer"
+                        }
                     }
 
-                    {composite_children} BasicState trafficlight_root_main_trafficlight_normal_yellow {
+                    {composite_children} BasicState trafficlight_main_main_trafficlight_normal_yellow {
                         name = "yellow"
                         isInitial = False
+
+                        onEntryScript = $
+                                Void function onentry(attributes : Element):
+                                    dict_overwrite(attributes, "colour", "")
+                                    return!
+                            $
+
+                        {onEntryRaise} Raise {
+                            event = "displayYellow"
+                        }
+                        {onEntryRaise} Raise {
+                            event = "disableTimer"
+                        }
                     }
 
-                    {composite_children} HistoryState trafficlight_root_main_trafficlight_normal_hist {
+                    {composite_children} HistoryState trafficlight_main_main_trafficlight_normal_hist {
                         name = "hist"
                     }
                 }
 
-                {composite_children} CompositeState trafficlight_root_main_trafficlight_interrupted {
-                    {composite_children} BasicState trafficlight_root_main_trafficlight_interrupted_yellow {
+                {composite_children} CompositeState trafficlight_main_main_trafficlight_interrupted {
+                    {composite_children} BasicState trafficlight_main_main_trafficlight_interrupted_yellow {
                         name = "yellow"
                         isInitial = True
+
+                        {onEntryRaise} Raise {
+                            event = "displayYellow"
+                        }
                     }
 
-                    {composite_children} BasicState trafficlight_root_main_trafficlight_interrupted_black {
+                    {composite_children} BasicState trafficlight_main_main_trafficlight_interrupted_black {
                         name = "black"
                         isInitial = False
+
+                        {onEntryRaise} Raise {
+                            event = "displayNone"
+                        }
                     }
                 }
             }
 
-            {parallel_children} CompositeState trafficlight_root_main_timer {
+            {parallel_children} CompositeState trafficlight_main_main_timer {
                 name = "timer"
                 isInitial = False
 
-                {composite_children} BasicState trafficlight_root_main_timer_disabled {
+                {composite_children} BasicState trafficlight_main_main_timer_disabled {
                     name = "disabled"
                     isInitial = False
                 }
 
-                {composite_children} BasicState trafficlight_root_main_timer_running {
+                {composite_children} CompositeState trafficlight_main_main_timer_running {
                     name = "running"
                     isInitial = True
+
+                    {onExitRaise} Raise {
+                        event = "updateTimerValue"
+                        parameter = $
+                                Element function parameter(attributes : Element):
+                                    return -1!
+                            $
+                    }
+
+                    {composite_children} BasicState trafficlight_main_main_timer_running_decidingcolor {
+                        name = "decidingcolor"
+                        isInitial = True
+                    }
+
+                    {composite_children} BasicState trafficlight_main_main_timer_running_green {
+                        name = "green"
+                        isInitial = False
+
+                        {onEntryRaise} Raise {
+                            event = "updateTimerValue"
+                            parameter = $
+                                    Element function raise(attributes : Element):
+                                        return attributes["counter"]!
+                                $
+                        }
+                    }
+
+                    {composite_children} BasicState trafficlight_main_main_timer_running_red {
+                        name = "red"
+                        isInitial = False
+
+                        {onEntryRaise} Raise {
+                            event = "updateTimerValue"
+                            parameter = $
+                                    Element function raise(attributes : Element):
+                                        return attributes["counter"]!
+                                $
+                        }
+                    }
                 }
             }
         }
     }
 }
+
+transition (trafficlight_main_off, trafficlight_main_main) {
+    name = "toggle"
+    event = "toggle"
+}
+
+transition (trafficlight_main_main, trafficlight_main_off) {
+    name = "toggle"
+    event = "toggle"
+}
+
+transition (trafficlight_main_main_trafficlight_normal, trafficlight_main_main_trafficlight_interrupted) {
+    name = "police_interrupt / disableTimer"
+    event = "police_interrupt"
+
+    {transition_raises} Raise {
+        event = "disableTimer"
+    }
+}
+
+transition (trafficlight_main_main_trafficlight_interrupted, trafficlight_main_main_trafficlight_normal_hist) {
+    name = "police_interrupt / enableTimer"
+    event = "police_interrupt"
+
+    {transition_raises} Raise {
+        event = "enableTimer"
+    }
+}
+
+transition (trafficlight_main_main_trafficlight_normal_red, trafficlight_main_main_trafficlight_normal_green) {
+    name = "after 60s"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 60.0!
+        $
+}
+
+transition (trafficlight_main_main_trafficlight_normal_green, trafficlight_main_main_trafficlight_normal_yellow) {
+    name = "after 55s"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 55.0!
+        $
+}
+
+transition (trafficlight_main_main_trafficlight_normal_yellow, trafficlight_main_main_trafficlight_normal_red) {
+    name = "after 5s"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 5.0!
+        $
+
+    {transition_raises} Raise {
+        event = "enableTimer"
+    }
+}
+
+transition (trafficlight_main_main_trafficlight_interrupted_yellow, trafficlight_main_main_trafficlight_interrupted_black) {
+    name = "after 500ms"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 0.5!
+        $
+}
+
+transition (trafficlight_main_main_trafficlight_interrupted_black, trafficlight_main_main_trafficlight_interrupted_yellow) {
+    name = "after 500ms"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 0.5!
+        $
+}
+
+transition (trafficlight_main_main_timer_disabled, trafficlight_main_main_timer_running) {
+    name = "enableTimer"
+    event = "enableTimer"
+}
+
+transition (trafficlight_main_main_timer_running, trafficlight_main_main_timer_disabled) {
+    name = "disableTimer"
+    event = "disableTimer"
+}
+
+transition (trafficlight_main_main_timer_running, trafficlight_main_main_timer_running) {
+    name = "resetTimer"
+    event = "resetTimer"
+}
+
+transition (trafficlight_main_main_timer_running_decidingcolor, trafficlight_main_main_timer_running_green) {
+    name = "[green] / updateTimerColour"
+    cond = $
+            Boolean function cond(attributes : Element, parameters : Element):
+                return value_eq(attributes["colour"], "green")!
+        $
+
+    {transition_raises} Raise {
+        event = "updateTimerColour"
+        parameter = $
+                Element function param(attributes : Element, parameters : Element):
+                    return "green"!
+            $
+    }
+}
+
+transition (trafficlight_main_main_timer_running_decidingcolor, trafficlight_main_main_timer_running_red) {
+    name = "[red] / updateTimerColour"
+    cond = $
+            Boolean function cond(attributes : Element, parameters : Element):
+                return value_eq(attributes["colour"], "red")!
+        $
+
+    {transition_raises} Raise {
+        event = "updateTimerColour"
+        parameter = $
+                Element function param(attributes : Element, parameters : Element):
+                    return "red"!
+            $
+    }
+}
+
+transition (trafficlight_main_main_timer_running_red, trafficlight_main_main_timer_running_red) {
+    name = "after 1s / counter -= 1"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 1.0!
+        $
+    script = $
+            Void function script(attributes : Element, parameters : Element):
+                dict_overwrite(attributes, "counter", integer_subtraction(attributes["counter"], 1))
+                return!
+        $
+}
+
+transition (trafficlight_main_main_timer_running_green, trafficlight_main_main_timer_running_green) {
+    name = "after 1s / counter -= 1"
+    after = $
+            Float function after(attributes : Element, parameters : Element):
+                return 1.0!
+        $
+    script = $
+            Void function script(attributes : Element, parameters : Element):
+                dict_overwrite(attributes, "counter", integer_subtraction(attributes["counter"], 1))
+                return!
+        $
+}