/** * Statechart compiler by Glenn De Jonghe * Javascript generator by Joeri Exelmans * * Date: Tue Jun 26 11:21:44 2018 * * Model author: Simon Van Mierlo * Model name: DebuggingEnvironment * Model description: Debugging environment for Dynamic Structure DEVS in HTML + JS (d3/w2ui). */ // put everything in an object (serves as "namespace") DebuggingEnvironment = {}; // closure scope (function() { // The actual constructor var MainApp = function(controller) { MainApp.prototype.commonConstructor.call(this,controller); // constructor body (user-defined) }; MainApp.prototype = new RuntimeClassBase(); // Unique IDs for all statechart nodes MainApp.prototype.Root = 0; MainApp.prototype.Root_creating_toolbar = 1; MainApp.prototype.Root_creating_visualizer = 2; MainApp.prototype.Root_running = 3; // Statechart enter/exit action method(s) : MainApp.prototype.enter_Root_creating_toolbar = function() { this.object_manager.addEvent(new Event("create_instance", null, [this, 'toolbar','DebuggingToolbar'])); this.current_state[this.Root].push(this.Root_creating_toolbar); }; MainApp.prototype.exit_Root_creating_toolbar = function() { this.current_state[this.Root] = new Array(); }; MainApp.prototype.enter_Root_creating_visualizer = function() { this.object_manager.addEvent(new Event("create_instance", null, [this, 'visualizer','Visualizer'])); this.current_state[this.Root].push(this.Root_creating_visualizer); }; MainApp.prototype.exit_Root_creating_visualizer = function() { this.current_state[this.Root] = new Array(); }; MainApp.prototype.enter_Root_running = function() { this.current_state[this.Root].push(this.Root_running); }; MainApp.prototype.exit_Root_running = function() { this.current_state[this.Root] = new Array(); }; // Statechart transitions : MainApp.prototype.transition_Root = function(event) { var catched = false; if (!catched) { if (this.current_state[this.Root][0] === this.Root_creating_toolbar) { catched = this.transition_Root_creating_toolbar(event); } else if (this.current_state[this.Root][0] === this.Root_creating_visualizer) { catched = this.transition_Root_creating_visualizer(event); } else if (this.current_state[this.Root][0] === this.Root_running) { catched = this.transition_Root_running(event); } } return catched; }; MainApp.prototype.transition_Root_creating_toolbar = function(event) { var catched = false; var enableds = new Array(); if (event.name === "instance_created") { enableds.push(1); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_creating_toolbar. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var association_name = parameters[0]; this.exit_Root_creating_toolbar(); this.object_manager.addEvent(new Event("start_instance", null, [this, association_name])); this.enter_Root_creating_visualizer(); } catched = true; } return catched; }; MainApp.prototype.transition_Root_creating_visualizer = function(event) { var catched = false; var enableds = new Array(); if (event.name === "instance_created") { enableds.push(1); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_creating_visualizer. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var association_name = parameters[0]; this.exit_Root_creating_visualizer(); this.object_manager.addEvent(new Event("start_instance", null, [this, association_name])); this.enter_Root_running(); } catched = true; } return catched; }; MainApp.prototype.transition_Root_running = function(event) { var catched = false; return catched; }; // Execute transitions MainApp.prototype.transition = function(event) { if (!event) event = new Event(); this.state_changed = this.transition_Root(event); }; // inState method for statechart MainApp.prototype.inState = function(nodes) { for (var c in this.current_state) { if (!this.current_state.hasOwnProperty(c)) continue; var new_nodes = new Array(); for (var n in nodes) { if (!nodes.hasOwnProperty(n)) continue; if (this.current_state[c].indexOf(nodes[n]) === -1) { new_nodes.push(nodes[n]); } } nodes = new_nodes; if (nodes.length === 0) { return true; } } return false; }; MainApp.prototype.commonConstructor = function(controller) { if (!controller) controller = null; // Constructor part that is common for all constructors. RuntimeClassBase.call(this); // User defined input ports this.inports = new Object(); this.controller = controller; this.object_manager = (controller == null ? null : controller.object_manager); this.current_state = new Object(); this.history_state = new Object(); // Initialize statechart this.current_state[this.Root] = new Array(); }; MainApp.prototype.start = function() { RuntimeClassBase.prototype.start.call(this); this.enter_Root_creating_toolbar(); }; // put class in global diagram object DebuggingEnvironment.MainApp = MainApp; // The actual constructor var DebuggingToolbar = function(controller) { DebuggingToolbar.prototype.commonConstructor.call(this,controller); // constructor body (user-defined) this.visualized_simulator = "NETLOGO" this.parameters = {}; this.buttons = {}; this.curr_parameter = null; this.button_counter = 0; if (this.visualized_simulator == "NETLOGO") { this.buttons_to_create = [{parent: this, description: 'Simulate', icon: 'simulate', command: 'simulate'}, {parent: this, description: 'Realtime Simulate', icon: 'simulatert', command: 'realtime', parameter_needed: 'realtime_scale'}, {parent: this, description: 'Realtime Scale', html: 'input size="1" value="1.0" style="border: 1px solid silver"', default: 1.0, parameter: 'realtime_scale'}, {parent: this, description: 'Pause', icon: 'pause', command: 'pause'}, {parent: this, description: 'Big Step', icon: 'bigstep', command: 'big_step'}, {parent: this, description: 'Reset', icon: 'reset', command: 'reset'}, {parent: this, description: 'Add Breakpoint', icon: 'breakpoint', action: function() {breakpoint_dialog.dialog( "open" );}}]; } else { this.buttons_to_create = [{parent: this, description: 'Simulate', icon: 'simulate', command: 'simulate'}, {parent: this, description: 'Realtime Simulate', icon: 'simulatert', command: 'realtime', parameter_needed: 'realtime_scale'}, {parent: this, description: 'Realtime Scale', html: 'input size="1" value="1.0" style="border: 1px solid silver"', default: 1.0, parameter: 'realtime_scale'}, {parent: this, description: 'Pause', icon: 'pause', command: 'pause'}, {parent: this, description: 'Big Step', icon: 'bigstep', command: 'big_step'}, {parent: this, description: 'Small Step', icon: 'smallstep', command: 'small_step'}, {parent: this, description: 'Reset', icon: 'reset', command: 'reset'}, {parent: this, description: 'Add Breakpoint', icon: 'breakpoint', action: function() {breakpoint_dialog.dialog( "open" );}}]; } this.tb = ui.create_toolbar('DebuggingToolbar'); }; DebuggingToolbar.prototype = new RuntimeClassBase(); // Unique IDs for all statechart nodes DebuggingToolbar.prototype.Root = 0; DebuggingToolbar.prototype.Root_initializing = 1; DebuggingToolbar.prototype.Root_initializing_check = 2; DebuggingToolbar.prototype.Root_initializing_creating_button = 3; DebuggingToolbar.prototype.Root_initializing_running = 4; DebuggingToolbar.prototype.Root_initializing_getting_parameter = 5; // Statechart enter/exit action method(s) : DebuggingToolbar.prototype.enter_Root_initializing = function() { this.current_state[this.Root].push(this.Root_initializing); }; DebuggingToolbar.prototype.exit_Root_initializing = function() { if (this.current_state[this.Root_initializing].indexOf(this.Root_initializing_check) !== -1) { this.exit_Root_initializing_check(); } if (this.current_state[this.Root_initializing].indexOf(this.Root_initializing_creating_button) !== -1) { this.exit_Root_initializing_creating_button(); } if (this.current_state[this.Root_initializing].indexOf(this.Root_initializing_running) !== -1) { this.exit_Root_initializing_running(); } if (this.current_state[this.Root_initializing].indexOf(this.Root_initializing_getting_parameter) !== -1) { this.exit_Root_initializing_getting_parameter(); } this.current_state[this.Root] = new Array(); }; DebuggingToolbar.prototype.enter_Root_initializing_check = function() { this.current_state[this.Root_initializing].push(this.Root_initializing_check); }; DebuggingToolbar.prototype.exit_Root_initializing_check = function() { this.current_state[this.Root_initializing] = new Array(); }; DebuggingToolbar.prototype.enter_Root_initializing_creating_button = function() { this.current_state[this.Root_initializing].push(this.Root_initializing_creating_button); }; DebuggingToolbar.prototype.exit_Root_initializing_creating_button = function() { this.current_state[this.Root_initializing] = new Array(); }; DebuggingToolbar.prototype.enter_Root_initializing_running = function() { this.current_state[this.Root_initializing].push(this.Root_initializing_running); }; DebuggingToolbar.prototype.exit_Root_initializing_running = function() { this.current_state[this.Root_initializing] = new Array(); }; DebuggingToolbar.prototype.enter_Root_initializing_getting_parameter = function() { this.current_state[this.Root_initializing].push(this.Root_initializing_getting_parameter); }; DebuggingToolbar.prototype.exit_Root_initializing_getting_parameter = function() { this.current_state[this.Root_initializing] = new Array(); }; // Statechart enter/exit default method(s) : DebuggingToolbar.prototype.enterDefault_Root_initializing = function() { this.enter_Root_initializing(); this.enter_Root_initializing_check(); }; // Statechart transitions : DebuggingToolbar.prototype.transition_Root = function(event) { var catched = false; if (!catched) { if (this.current_state[this.Root][0] === this.Root_initializing) { catched = this.transition_Root_initializing(event); } } return catched; }; DebuggingToolbar.prototype.transition_Root_initializing = function(event) { var catched = false; if (!catched) { if (this.current_state[this.Root_initializing][0] === this.Root_initializing_check) { catched = this.transition_Root_initializing_check(event); } else if (this.current_state[this.Root_initializing][0] === this.Root_initializing_creating_button) { catched = this.transition_Root_initializing_creating_button(event); } else if (this.current_state[this.Root_initializing][0] === this.Root_initializing_running) { catched = this.transition_Root_initializing_running(event); } else if (this.current_state[this.Root_initializing][0] === this.Root_initializing_getting_parameter) { catched = this.transition_Root_initializing_getting_parameter(event); } } return catched; }; DebuggingToolbar.prototype.transition_Root_initializing_check = function(event) { var catched = false; var enableds = new Array(); if (this.buttons_to_create.length > 0) { enableds.push(1); } if (this.buttons_to_create.length == 0) { enableds.push(2); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_initializing_check. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { this.exit_Root_initializing_check(); if ('parameter' in this.buttons_to_create[0]) { this.curr_parameter = this.buttons_to_create[0]['parameter'] } this.object_manager.addEvent(new Event("create_instance", null, [this, 'buttons','Button','button' + this.button_counter,this.tb,this.buttons_to_create.shift()])); this.enter_Root_initializing_creating_button(); } else if (enabled === 2) { this.exit_Root_initializing_check(); this.enter_Root_initializing_running(); } catched = true; } return catched; }; DebuggingToolbar.prototype.transition_Root_initializing_creating_button = function(event) { var catched = false; var enableds = new Array(); if (event.name === "instance_created") { enableds.push(1); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_initializing_creating_button. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var association_name = parameters[0]; this.exit_Root_initializing_creating_button(); this.object_manager.addEvent(new Event("start_instance", null, [this, association_name])); if (this.curr_parameter) { this.parameters[this.curr_parameter] = association_name; this.curr_parameter = null; } this.buttons['button' + this.button_counter] = association_name; this.button_counter += 1; this.enter_Root_initializing_check(); } catched = true; } return catched; }; DebuggingToolbar.prototype.transition_Root_initializing_running = function(event) { var catched = false; var enableds = new Array(); if (event.name === "get_parameter") { enableds.push(1); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_initializing_running. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var the_parameter = parameters[0]; var respond_id = parameters[1]; this.exit_Root_initializing_running(); var send_event = new Event("get_parameter", null, []); this.object_manager.addEvent(new Event("narrow_cast", null, [this, this.parameters[the_parameter] , send_event])); this.respond_id = respond_id; this.enter_Root_initializing_getting_parameter(); } catched = true; } return catched; }; DebuggingToolbar.prototype.transition_Root_initializing_getting_parameter = function(event) { var catched = false; var enableds = new Array(); if (event.name === "parameter_reply") { enableds.push(1); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_initializing_getting_parameter. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var parameter_value = parameters[0]; this.exit_Root_initializing_getting_parameter(); var send_event = new Event("parameter_reply", null, [parameter_value]); this.object_manager.addEvent(new Event("narrow_cast", null, [this, this.buttons[this.respond_id] , send_event])); this.enter_Root_initializing_running(); } catched = true; } return catched; }; // Execute transitions DebuggingToolbar.prototype.transition = function(event) { if (!event) event = new Event(); this.state_changed = this.transition_Root(event); }; // inState method for statechart DebuggingToolbar.prototype.inState = function(nodes) { for (var c in this.current_state) { if (!this.current_state.hasOwnProperty(c)) continue; var new_nodes = new Array(); for (var n in nodes) { if (!nodes.hasOwnProperty(n)) continue; if (this.current_state[c].indexOf(nodes[n]) === -1) { new_nodes.push(nodes[n]); } } nodes = new_nodes; if (nodes.length === 0) { return true; } } return false; }; DebuggingToolbar.prototype.commonConstructor = function(controller) { if (!controller) controller = null; // Constructor part that is common for all constructors. RuntimeClassBase.call(this); // User defined input ports this.inports = new Object(); this.controller = controller; this.object_manager = (controller == null ? null : controller.object_manager); this.current_state = new Object(); this.history_state = new Object(); // Initialize statechart this.current_state[this.Root] = new Array(); this.current_state[this.Root_initializing] = new Array(); }; DebuggingToolbar.prototype.start = function() { RuntimeClassBase.prototype.start.call(this); this.enterDefault_Root_initializing(); }; // put class in global diagram object DebuggingEnvironment.DebuggingToolbar = DebuggingToolbar; // The actual constructor var Button = function(controller, button_id, toolbar, parameters) { Button.prototype.commonConstructor.call(this,controller); // constructor body (user-defined) this.button_id = button_id; this.toolbar = toolbar; this.action = null; this.command = null; if ('parameter_needed' in parameters) { this.parameter_needed = parameters['parameter_needed']; } else { this.parameter_needed = null; } if ('html' in parameters) { var the_html = parameters['html'] the_html += ' id="' + this.button_id + '_input" onchange="ui.parameter_changed(\'' + button_id + '\');"' this.btn = ui.create_tb_element(this.button_id, '<' + the_html + ' />', parameters['default'], this.toolbar, this.controller, this.inports['button_ui_input']); } else if ('action' in parameters) { this.action = parameters['action']; this.btn = ui.create_button(this.button_id, parameters['description'], parameters['icon'], this.toolbar, this.controller, this.inports['button_ui_input']); } else { this.command = parameters['command']; this.btn = ui.create_button(this.button_id, parameters['description'], parameters['icon'], this.toolbar, this.controller, this.inports['button_ui_input']); } }; Button.prototype = new RuntimeClassBase(); // Unique IDs for all statechart nodes Button.prototype.Root = 0; Button.prototype.Root_listening = 1; Button.prototype.Root_getting_parameter = 2; // Statechart enter/exit action method(s) : Button.prototype.enter_Root_listening = function() { this.current_state[this.Root].push(this.Root_listening); }; Button.prototype.exit_Root_listening = function() { this.current_state[this.Root] = new Array(); }; Button.prototype.enter_Root_getting_parameter = function() { this.current_state[this.Root].push(this.Root_getting_parameter); }; Button.prototype.exit_Root_getting_parameter = function() { this.current_state[this.Root] = new Array(); }; // Statechart transitions : Button.prototype.transition_Root = function(event) { var catched = false; if (!catched) { if (this.current_state[this.Root][0] === this.Root_listening) { catched = this.transition_Root_listening(event); } else if (this.current_state[this.Root][0] === this.Root_getting_parameter) { catched = this.transition_Root_getting_parameter(event); } } return catched; }; Button.prototype.transition_Root_listening = function(event) { var catched = false; var enableds = new Array(); if (event.name === "mouse_press" && event.port === "button_ui_input") { if (this.action) { enableds.push(1); } } if (event.name === "mouse_press" && event.port === "button_ui_input") { if (this.parameter_needed == null && this.command) { enableds.push(2); } } if (event.name === "mouse_press" && event.port === "button_ui_input") { if (this.parameter_needed != null && this.command) { enableds.push(3); } } if (event.name === "get_parameter") { enableds.push(4); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_listening. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { this.exit_Root_listening(); this.action(); this.enter_Root_listening(); } else if (enabled === 2) { this.exit_Root_listening(); this.controller.outputEvent(new Event("debugging_command", "output", [this.command])); this.enter_Root_listening(); } else if (enabled === 3) { this.exit_Root_listening(); var send_event = new Event("get_parameter", null, [this.parameter_needed,this.button_id]); this.object_manager.addEvent(new Event("narrow_cast", null, [this, 'parent' , send_event])); this.enter_Root_getting_parameter(); } else if (enabled === 4) { this.exit_Root_listening(); var send_event = new Event("parameter_reply", null, [this.btn.value]); this.object_manager.addEvent(new Event("narrow_cast", null, [this, 'parent' , send_event])); this.enter_Root_listening(); } catched = true; } return catched; }; Button.prototype.transition_Root_getting_parameter = function(event) { var catched = false; var enableds = new Array(); if (event.name === "parameter_reply") { enableds.push(1); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_getting_parameter. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var the_parameter = parameters[0]; this.exit_Root_getting_parameter(); var the_parameters = {}; the_parameters[this.parameter_needed] = the_parameter; this.controller.outputEvent(new Event("debugging_command", "output", [this.command,the_parameters])); this.enter_Root_listening(); } catched = true; } return catched; }; // Execute transitions Button.prototype.transition = function(event) { if (!event) event = new Event(); this.state_changed = this.transition_Root(event); }; // inState method for statechart Button.prototype.inState = function(nodes) { for (var c in this.current_state) { if (!this.current_state.hasOwnProperty(c)) continue; var new_nodes = new Array(); for (var n in nodes) { if (!nodes.hasOwnProperty(n)) continue; if (this.current_state[c].indexOf(nodes[n]) === -1) { new_nodes.push(nodes[n]); } } nodes = new_nodes; if (nodes.length === 0) { return true; } } return false; }; Button.prototype.commonConstructor = function(controller) { if (!controller) controller = null; // Constructor part that is common for all constructors. RuntimeClassBase.call(this); // User defined input ports this.inports = new Object(); this.inports["button_ui_input"] = controller.addInputPort("button_ui_input", this); this.controller = controller; this.object_manager = (controller == null ? null : controller.object_manager); this.current_state = new Object(); this.history_state = new Object(); // Initialize statechart this.current_state[this.Root] = new Array(); }; Button.prototype.start = function() { RuntimeClassBase.prototype.start.call(this); this.enter_Root_listening(); }; // put class in global diagram object DebuggingEnvironment.Button = Button; // The actual constructor var Visualizer = function(controller) { Visualizer.prototype.commonConstructor.call(this,controller); // constructor body (user-defined) this.visualized_simulator = "NETLOGO" the_controller = this.controller; this.simulation_info = d3.select("body").append("div") .attr("class", "simulationInfo") .style("margin", "5px") .style("display", "block"); this.simulation_time = this.simulation_info.append("span") .append("text") .text("SIMULATION TIME: (not started)") .style("float", "left"); this.simulation_steps = this.simulation_info.append("span") .style("margin", "5px") .style("float", "left") .attr("class", "invisibleInfo") .attr("id", "smallStepInfo"); this.simulation_steps.selectAll("div").data([0,1,2,3,4,5,6,7]) .enter() .append("div") .attr("id", function(d) {return "smallStepInfo_" + d}) .attr("class", "smallStepInfo inactive") .style("transform", function(d) {return "translate(" + d * 5 + "px, -4px) rotate(45deg)"}); d3.select("body").append("br"); this.breakpoint_info = d3.select("body").append("div") .attr("class", "breakpointInfo") .style("margin", "5px") .style("display", "block"); this.breakpoint_text = this.breakpoint_info.append("span") .append("text") .text("BREAKPOINTS: ") .style("float", "left"); this.breakpoint_infos = this.breakpoint_info.append("span") .style("margin", "5px") .style("float", "left") .attr("id", "breakpointInfos"); this.breakpoints = []; this.port_connections = []; this.loc_to_item = {}; event_to_inject = undefined; god_event_to_process = undefined; // TODO: this is domain-specific! this.particle_id_to_item = {}; var margin = {top: 50, right: 0, bottom: 0, left: 0}, width = 960 - margin.right - margin.left, height = 1024 - margin.top - margin.bottom; this.node_id = 0; if (this.visualized_simulator == "NETLOGO") { this.data = [{'name': '', 'children': [], 'loc': '', 'id': this.node_id}]; this.node_id++; } else { this.data = []; } this.tree = d3.layout.tree() .size([width, height]); this.diagonal = d3.svg.diagonal(); this.port_connection_diagonal = d3.svg.diagonal().projection(function(d) {return [d.x, d.y]}); this.parent_svg = d3.select("body").append("svg") .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom); var defs = this.parent_svg.append('svg:defs') var markers = [{name: 'arrow', path: 'M2,2 L2,11 L10,6 L2,2', fill: "red"}, {name: 'arrow_green', path: 'M2,2 L2,11 L10,6 L2,2', fill: "green"}]; var marker = defs.selectAll('marker') .data(markers) .enter() .append('svg:marker') .attr('id', function(d){ return 'marker_' + d.name}) .attr('markerHeight', 13) .attr('markerWidth', 13) .attr('markerUnits', 'strokeWidth') .attr('orient', 'auto') .attr('refX', 2) .attr('refY', 6) .append('svg:path') .attr('d', function(d){ return d.path }) .attr('fill', function(d){ return d.fill }); this.svg = this.parent_svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); this_object = this; function godEvent() { if (this_object.visualized_simulator == "NETLOGO") { god_event_to_process = {'turtle': $('#currLoc').text(), 'attribute': $('#godEventName').val(), 'value': eval($('#godEventValue').val())}; the_controller.addInput(new Event("process_god_event", "ui_input", [god_event_to_process]), 0.0); dialog.dialog("close"); } else { god_event_to_process = {'model': $('#currLoc').text(), 'attribute': $('#godEventName').val(), 'value': eval($('#godEventValue').val())}; the_controller.addInput(new Event("process_god_event", "ui_input", [god_event_to_process]), 0.0); dialog.dialog("close"); } } dialog = $( "#godEventPopup" ).dialog({ autoOpen: false, height: 200, width: 325, modal: true, buttons: { "Submit": godEvent, Cancel: function() { dialog.dialog( "close" ); } }, close: function() { form[ 0 ].reset(); } }).css("font-size", "14px");; form = dialog.find( "form" ).on( "submit", function( event ) { event.preventDefault(); godEvent(); }); function injectEvent() { event_to_inject = {'port': $('#currLoc').text(), 'event': eval($('#injectEvent').val()), 'time': eval($('#injectTime').val())}; the_controller.addInput(new Event("inject_event", "ui_input", [event_to_inject]), 0.0); inject_dialog.dialog("close"); } inject_dialog = $( "#injectEventPopup" ).dialog({ autoOpen: false, height: 200, width: 325, modal: true, buttons: { "Submit": injectEvent, Cancel: function() { inject_dialog.dialog( "close" ); } }, close: function() { inject_form[ 0 ].reset(); } }).css("font-size", "14px"); inject_form = inject_dialog.find( "form" ).on( "submit", function( event ) { event.preventDefault(); injectEvent(); }); if (this.visualized_simulator == "NETLOGO") { $('#breakpointFunction').text("def breakpoint(time, turtles):\n") } function addBreakpoint() { breakpoint_to_add = [$('#breakpointName').val(), $('#breakpointFunction').val(), $('#breakpointEnabled').is(":checked"), $('#breakpointDisableOnTrigger').is(":checked")]; the_controller.addInput(new Event("add_breakpoint", "ui_input", [breakpoint_to_add]), 0.0); breakpoint_dialog.dialog("close"); } breakpoint_dialog = $( "#breakpointPopup" ).dialog({ autoOpen: false, height: 400, width: 600, modal: true, buttons: { "Submit": addBreakpoint, Cancel: function() { breakpoint_dialog.dialog( "close" ); } }, close: function() { breakpoint_form[ 0 ].reset(); } }).css("font-size", "14px"); breakpoint_form = breakpoint_dialog.find( "form" ).on( "submit", function( event ) { event.preventDefault(); addBreakpoint(); }); }; Visualizer.prototype = new RuntimeClassBase(); // Unique IDs for all statechart nodes Visualizer.prototype.Root = 0; Visualizer.prototype.Root_initializing = 1; Visualizer.prototype.Root_running = 2; // User defined method Visualizer.prototype.update_vis = function(structural_changes) { if (this.visualized_simulator == "NETLOGO") { var created_turtles = [], deleted_turtles = []; if ('CREATED_TURTLES' in structural_changes) { created_turtles = structural_changes['CREATED_TURTLES']; } if ('DELETED_TURTLES' in structural_changes) { deleted_turtles = structural_changes['DELETED_TURTLES']; } var node_id = this.node_id; var loc_to_item = this.loc_to_item; var data = this.data; created_turtles.forEach(function(item) { var node = {'name': 'turtle[' + item + ']', 'children': [], 'id': node_id++, 'turtle_id': item} if (!data[0].hasOwnProperty('children')) { data[0]['children'] = []; } data[0].children.push(node); loc_to_item[item] = node; }); deleted_turtles.forEach(function(item) { curr_array = data; data[0]['children'] = data[0]['children'].filter(function(el) {return el['name'] != ('turtle[' + item + ']')}); }); this.node_id = node_id; this.data = data; var nodes = this.tree.nodes(this.data[0]), links = this.tree.links(nodes); nodes.forEach(function(d, i) { d.y = d.depth * 100 + i * 40; }); // Declare the nodes... var node = this.svg.selectAll("g.node") .data(nodes, function(d) { return d.id; }); // Enter the nodes. var nodeEnter = node.enter().append("g") .attr("class", "node") .attr("id", function(d) {return 'instance_' + d.id;}) .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); nodeEnter.append("rect") .attr("width", 120) .attr("height", 25) .attr("transform", "translate(-60, 0)") .on("click", function(d) { console.log(JSON.stringify(d.state, null, 2)); }) .on("mouseover", function(d) { var node = d3.select("#instance_" + d.id) var stateInfo = node.selectAll(".stateInfo") .data(function(n) {if (n.state) {return [n.state]} else {return []}}, function(d) {return d.id}); var stateInfoEnter = stateInfo.enter().append("text") .attr("transform", "translate(-60, 60)") .attr("id", this.node_id++) .attr("class", "stateInfo"); var stateInfoText = stateInfo.selectAll("tspan") .data(function(d) {return JSON.stringify(d, null, 2).split("\n")}); var stateInfoTextEnter = stateInfoText.enter().append("tspan") .attr("x", "0.0") .attr("dy", "1.4em") .attr("xml:space", "preserve") .text(function(d) {return d}); }) .on("mouseout", function(d) { var node = d3.select("#instance_" + d.id) var stateInfo = node.selectAll(".stateInfo"); stateInfo.selectAll("tspan").data([]).exit().remove(); }) .on("contextmenu", function (d, i) { $( "#currLoc" ).html(d.turtle_id); d3.event.preventDefault(); if (!d.children) { dialog.dialog( "open" ); } }); nodeEnter.append("text") .attr("y", 12) .attr("dy", ".35em") .attr("text-anchor", "middle") .text(function(d) { return d.name; }) .style("fill-opacity", 1); // Declare the links... var link = this.svg.selectAll("path.link") .data(links); // Enter the links. link.enter().insert("path", "g") .attr("class", "link") .attr("d", this.diagonal); // Update the nodes. node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); node.classed("coupled", function(d) {return d.name == ''}); // Transition links to their new position. link.attr("d", this.diagonal); // Remove nodes and links. node.exit().remove(); link.exit().remove(); } else { d3.select("#smallStepInfo_7").classed("inactive", false); var created_models = [], created_ports = [], connected_ports = [], deleted_models = [], deleted_ports = [], disconnected_ports = []; if ('CREATED_MODELS' in structural_changes) { created_models = structural_changes['CREATED_MODELS']; } if ('CREATED_PORTS' in structural_changes) { created_ports = structural_changes['CREATED_PORTS']; } if ('CONNECTED_PORTS' in structural_changes) { connected_ports = structural_changes['CONNECTED_PORTS']; } if ('DELETED_MODELS' in structural_changes) { deleted_models = structural_changes['DELETED_MODELS']; } if ('DELETED_PORTS' in structural_changes) { deleted_ports = structural_changes['DELETED_PORTS']; } if ('DISCONNECTED_PORTS' in structural_changes) { disconnected_ports = structural_changes['DISCONNECTED_PORTS']; } // sort according to their depth (amounts of dots in their name) created_models.sort(function(a, b) { return (a.match(/./g) || []).length - (b.match(/./g) || []).length }) data = this.data; var node_id = this.node_id; var loc_to_item = this.loc_to_item; created_models.forEach(function(item) { splitted_path = item.split('.'); element_to_insert = data; while (splitted_path.length > 1) { curr_name = splitted_path.shift(); element_to_insert = element_to_insert.find(function(el) {return el['name'] == curr_name}).children; } var node = {'name': splitted_path[0], 'children': [], 'ports': [], 'loc': item, 'id': node_id++} element_to_insert.push(node); loc_to_item[item] = node; }); created_ports.forEach(function(item) { splitted_path = item[0].split('.'); curr_array = data; while (splitted_path.length > 2) { curr_name = splitted_path.shift(); curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children; } ports = curr_array.find(function(el) {return el['name'] == splitted_path[0]})['ports']; var node = {'name': splitted_path[1], 'is_input': item[1], 'loc': item[0], 'id': node_id++}; ports.push(node); loc_to_item[item[0]] = node; }); this.node_id = node_id; port_connections = this.port_connections connected_ports.forEach(function(item) { splitted_path_src = item[0].split('.'); curr_array = data; while (splitted_path_src.length > 2) { curr_name = splitted_path_src.shift(); curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children; } src_parent = curr_array.find(function(el) {return el['name'] == splitted_path_src[0]}); src = src_parent['ports'].find(function(el) {return el['name'] == splitted_path_src[1]}); splitted_path_dst = item[1].split('.'); curr_array = data; while (splitted_path_dst.length > 2) { curr_name = splitted_path_dst.shift(); curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children; } dst_parent = curr_array.find(function(el) {return el['name'] == splitted_path_dst[0]}); dst = dst_parent['ports'].find(function(el) {return el['name'] == splitted_path_dst[1]}); port_connections.push({'source': src, 'target': dst}); }); disconnected_ports.forEach(function(item) { port_connections = port_connections.filter(function(el) {return el.source.loc != item[0] || el.target.loc != item[1];}); }); this.port_connections = port_connections deleted_ports.forEach(function(item) { splitted_path = item.split('.'); curr_array = data; while (splitted_path.length > 2) { curr_name = splitted_path.shift(); curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children; } parent = curr_array.find(function(el) {return el['name'] == splitted_path[0]}); parent['ports'] = parent['ports'].filter(function(el) {return el['name'] != splitted_path[1]}); }); deleted_models.forEach(function(item) { splitted_path = item.split('.'); curr_array = data; while (splitted_path.length > 2) { curr_name = splitted_path.shift(); curr_array = element_to_insert.find(function(el) {return el['name'] == curr_name}).children; } parent = curr_array.find(function(el) {return el['name'] == splitted_path[0]}); parent['children'] = parent['children'].filter(function(el) {return el['name'] != splitted_path[1]}); }); this.data = data; var nodes = this.tree.nodes(this.data[0]), links = this.tree.links(nodes); nodes.forEach(function(d, i) { d.y = d.depth * 100 + i * 40 d.ports.forEach(function(p, i) {p.dx = 13, p.dy = 18; p.x = (d.x - 40) + i * p.dx; p.y = d.y + p.dy;}); }); // Declare the nodes... var node = this.svg.selectAll("g.node") .data(nodes, function(d) { return d.id; }); // Enter the nodes. var nodeEnter = node.enter().append("g") .attr("class", "node") .attr("id", function(d) {return 'instance_' + d.id;}) .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); nodeEnter.append("rect") .attr("width", 120) .attr("height", 25) .attr("transform", "translate(-60, 0)") .on("click", function(d) { console.log(JSON.stringify(d.state, null, 2)); }) .on("mouseover", function(d) { var node = d3.select("#instance_" + d.id) var stateInfo = node.selectAll(".stateInfo") .data(function(n) {if (n.state) {return [n.state]} else {return []}}, function(d) {return d.id}); var stateInfoEnter = stateInfo.enter().append("text") .attr("transform", "translate(-60, 60)") .attr("id", this.node_id++) .attr("class", "stateInfo"); var stateInfoText = stateInfo.selectAll("tspan") .data(function(d) {return JSON.stringify(d, null, 2).split("\n")}); var stateInfoTextEnter = stateInfoText.enter().append("tspan") .attr("x", "0.0") .attr("dy", "1.4em") .attr("xml:space", "preserve") .text(function(d) {return d}); }) .on("mouseout", function(d) { var node = d3.select("#instance_" + d.id) var stateInfo = node.selectAll(".stateInfo"); stateInfo.selectAll("tspan").data([]).exit().remove(); }) .on("contextmenu", function (d, i) { $( "#currLoc" ).html(d.loc); d3.event.preventDefault(); if (!d.children) { dialog.dialog( "open" ); } }); nodeEnter.append("text") .attr("y", 12) .attr("dy", ".35em") .attr("text-anchor", "middle") .text(function(d) { return d.name; }) .style("fill-opacity", 1); nodeEnter.append("text") .attr("class", "timeNext") .attr("y", -10) .attr("x", 30) .attr("dy", ".35em") .attr("text-anchor", "middle") .text("TN: --") .style("fill-opacity", 1); port = node.selectAll("g.port") .data(function(n) {return n.ports}, function(d) { return d.id; }) portEnter = port.enter().append("g") .attr("class", "port invisible") .attr("id", function(d) {return 'port_' + d.id;}) .on("mouseover", function(d) { d3.selectAll(".source_" + d.id).classed("invisibleLink", false) .classed("input", false); d3.selectAll(".target_" + d.id).classed("invisibleLink", false) .classed("input", true); port_connections.forEach(function(port_connection) { if (port_connection.source.id == d.id) { d3.select('#port_' + port_connection.target.id).attr("class", "port visible"); } else if (port_connection.target.id == d.id) { d3.select('#port_' + port_connection.source.id).attr("class", "port visible"); } }); d3.select(this).attr("class", "port visible"); }) .on("mouseout", function(d) { d3.selectAll(".source_" + d.id).classed("invisibleLink", true); d3.selectAll(".target_" + d.id).classed("invisibleLink", true); d3.selectAll(".port").attr("class", "port invisible"); }) .on("click", function (d, i) { $('#currLoc').html(d.loc); d3.event.preventDefault(); if (d.is_input) { inject_dialog.dialog( "open" ); } }); portEnter.append("rect") .attr("width", 10) .attr("height", 10) .style("fill", function(d) {return d.is_input ? "green" : "purple";}) .attr("transform", "rotate(45)"); portEnter.append("text") .attr("dy", ".35em") .attr("text-anchor", "left") .text(function(d) {return d.name;}) .attr("transform", "translate(0, 20) rotate(30)"); port.attr("transform", function(d, i) {return "translate(" + (-40 + i * d.dx) + ", " + d.dy + ")"}); // Declare the links... var link = this.svg.selectAll("path.link") .data(links); // Enter the links. link.enter().insert("path", "g") .attr("class", "link") .attr("d", this.diagonal); // Declare port connections... var port_connection = this.svg.selectAll("path.portConnection") .data(port_connections); // Enter port connections. port_connection.enter().insert("path", "g") .attr("class", "invisibleLink portConnection"); // Update the nodes. node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); node.classed("coupled", function(d) {return d.children}); // Transition links to their new position. link.attr("d", this.diagonal); // Transition links to their new position. port_connection.attr("d", function(d) { var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math.sqrt(dx * dx + dy * dy)/4, mx = d.source.x + dx/2, my = d.source.y + dy/2 + 30; return [ "M",d.source.x,d.source.y+5, "T",mx,my, "T",d.target.x,d.target.y+5 ].join(" "); }) .attr("class", function(d) {return "invisibleLink portConnection source_" + d.source.id + " target_" + d.target.id}); // Remove nodes and links. node.exit().remove(); link.exit().remove(); port.exit().remove(); port_connection.exit().remove(); } }; // User defined method Visualizer.prototype.visualize_initial_state = function(initial_states) { if (this.visualized_simulator == "NETLOGO") { for (var loc in initial_states) { var item = this.loc_to_item[loc]; item.state = initial_states[loc]; } } else { d3.select("#smallStepInfo").classed("invisibleInfo", true); d3.selectAll("g.node").attr("class", "node") .classed("coupled", function(d) {return d.children}); d3.selectAll("circle.inmessage").data([]).exit().remove(); d3.selectAll("circle.outmessage").data([]).exit().remove(); d3.selectAll(".portConnection").classed("invisibleLink", true); d3.selectAll(".port").classed("visible", false); d3.selectAll(".port").classed("invisible", true); d3.selectAll(".stateInfo").data([]).exit().remove(); for (var loc in initial_states) { var item = this.loc_to_item[loc]; d3.select("#instance_" + item.id + " .timeNext").text("TN: " + initial_states[loc][0][0] + "/" + initial_states[loc][0][1]) item.state = initial_states[loc][1]; if (item.state.particle_id) { this.particle_id_to_item[item.state.particle_id] = item; // TODO: this is somewhat ugly, we're making a lot of assumptions here and it's no longer domain-independent! } } } }; // User defined method Visualizer.prototype.visualize_new_state = function(new_states, new_tn) { d3.select("#smallStepInfo").classed("invisibleInfo", true); d3.selectAll("g.node").attr("class", "node") .classed("coupled", function(d) {return d.children}); d3.selectAll("circle.inmessage").data([]).exit().remove(); d3.selectAll("circle.outmessage").data([]).exit().remove(); d3.selectAll(".portConnection").classed("invisibleLink", true); d3.selectAll(".port").classed("visible", false); d3.selectAll(".port").classed("invisible", true); d3.selectAll(".stateInfo").data([]).exit().remove(); for (var loc in new_tn) { var item = this.loc_to_item[loc]; d3.select("#instance_" + item.id + " .timeNext").text("TN: " + new_tn[loc][0] + "/" + new_tn[loc][1]) item.state = new_states[loc]; if (item.state.particle_id != undefined) { this.particle_id_to_item[item.state.particle_id] = item; // TODO: this is somewhat ugly, we're making a lot of assumptions here and it's no longer domain-independent! } } }; // User defined method Visualizer.prototype.visualize_imminents = function(imminents) { d3.selectAll(".portConnection").classed("invisibleLink", true); d3.selectAll(".port").classed("visible", false); d3.selectAll(".port").classed("invisible", true); d3.selectAll("circle.inmessage").data([]).exit().remove(); d3.selectAll("circle.outmessage").data([]).exit().remove(); if (this.transitioning_nodes) { this.transitioning_nodes.forEach(function(n) {n.attr("class", "node") .classed("coupled", function(d) {return d.children});}); } d3.select("#smallStepInfo").classed("invisibleInfo", false); d3.selectAll(".smallStepInfo").classed("inactive", true); d3.select("#smallStepInfo_0").classed("inactive", false); var loc_to_item = this.loc_to_item; this.imminents = imminents; imminents.forEach(function(imminent) { d3.select("#instance_" + loc_to_item[imminent].id).classed("imminent", true); }) }; // User defined method Visualizer.prototype.visualize_selected_imminent = function(selected_imminent) { d3.select("#smallStepInfo_1").classed("inactive", false); var loc_to_item = this.loc_to_item; this.imminents.forEach(function(imminent) { if (!(imminent == selected_imminent)) { d3.select("#instance_" + loc_to_item[imminent].id).classed("imminent", false); } }) }; // User defined method Visualizer.prototype.visualize_messages = function(bag, msg_type) { var total_msgs = []; for (var key in bag) { var msgs = bag[key]; var port = this.loc_to_item[key]; if (port != undefined) { msgs[0].port = port; Array.prototype.push.apply(total_msgs, msgs); } } var msgs_vis = this.svg.selectAll("circle." + msg_type) .data(total_msgs); var msg_enter = msgs_vis.enter().append("circle") .attr("class", msg_type) .attr("id", function(m) {return "msg_" + m.port.id;}) .attr("r", 5) .attr("transform", function(m) {return "translate(" + m.port.x + "," + (m.port.y + 22) + ")"}) .on("click", function(d) {console.log(d[0])}); }; // User defined method Visualizer.prototype.visualize_inbags = function(inbags) { d3.select("#smallStepInfo_3").classed("inactive", false); function transition(circle, path, source_port_vis, target_port_vis) { circle.transition() .duration(3000) .attrTween("transform", translateAlong(path.node())) .each("end", function() { path.classed("invisibleLink", true); source_port_vis.classed("invisible", true); target_port_vis.classed("invisible", true); source_port_vis.classed("visible", false); target_port_vis.classed("visible", false); circle.attr("class", "inmessage"); }); } // Returns an attrTween for translating along the specified path element. function translateAlong(path) { var l = path.getTotalLength(); return function(d, i, a) { return function(t) { var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + (p.y + 17) + ")"; }; }; } var outports_visited = [] for (var key in inbags) { if (inbags[key].length == 2) { var msgs = inbags[key][1]; var inport = this.loc_to_item[key]; if (inport != undefined) { var circle = undefined; var outport_id = this.loc_to_item[inbags[key][0]].id; if (outports_visited.indexOf(outport_id) > -1) { circle = d3.select('#msg_' + outport_id); var parent = d3.select(circle.node().parentNode); circle = parent.append("circle") .attr("class", "outmessage") .attr("id", circle.id + outports_visited.indexOf(outport_id)) .attr("r", 5) .attr("transform", circle.transform) .on("click", (function(msgs) {return function(d) {console.log(msgs[0])}})(msgs)); } else { circle = d3.select('#msg_' + outport_id); circle.on("click", (function(msgs) {return function(d) {console.log(msgs[0])}})(msgs)); } var path = d3.select(".source_" + outport_id + ".target_" + inport.id); var source_port_vis = d3.select("#port_" + outport_id) var target_port_vis = d3.select("#port_" + inport.id) source_port_vis.classed("invisible", false); target_port_vis.classed("invisible", false); source_port_vis.classed("visible", true); target_port_vis.classed("visible", true); path.classed("invisibleLink", false); transition(circle, path, source_port_vis, target_port_vis); outports_visited.push(outport_id); } } else { var msgs = inbags[key][0]; var inport = this.loc_to_item[key]; this.svg.append("circle") .attr("class", "inmessage") .attr("id", "msg_" + inport.id) .attr("r", 5) .attr("transform", "translate(" + inport.x + "," + (inport.y + 22) + ")") .on("click", (function(msgs) {return function(d) {console.log(msgs[0])}})(msgs)); } } }; // User defined method Visualizer.prototype.visualize_transitioning = function(transitioning) { var transitioning_nodes = []; var loc_to_item = this.loc_to_item; Object.keys(transitioning).forEach(function(key) { transitioning_nodes.push(d3.select("#instance_" + loc_to_item[key].id).classed(transitioning[key], true)); }); this.transitioning_nodes = transitioning_nodes; }; // User defined method Visualizer.prototype.handle_internal_state_change = function(new_internal_states) { d3.select("#smallStepInfo_5").classed("inactive", false); for (var loc in new_internal_states) { var item = this.loc_to_item[loc]; item.state = new_internal_states[loc]; } if (this.transitioning_nodes) { this.transitioning_nodes.forEach(function(n) {n.attr("class", "node") .classed("coupled", function(d) {return d.children});}); } var node = this.svg.selectAll("g.node"); var stateInfo = node.selectAll("g.state"); stateInfo.text(function(d) {return JSON.stringify(d);}); }; // User defined method Visualizer.prototype.visualize_new_tn = function(new_tn) { d3.select("#smallStepInfo_6").classed("inactive", false); for (var loc in new_tn) { var item = this.loc_to_item[loc]; d3.select("#instance_" + item.id + " .timeNext").text("TN: " + new_tn[loc][0] + "/" + new_tn[loc][1]) } }; // User defined method Visualizer.prototype.select_instance = function(instance_id) { d3.selectAll(".stateInfo").data([]).exit().remove(); if (instance_id in this.particle_id_to_item) { var d = this.particle_id_to_item[instance_id]; var node = d3.select("#instance_" + d.id) var stateInfo = node.selectAll(".stateInfo") .data(function(n) {if (n.state) {return [n.state]} else {return []}}, function(d) {return d.id}); var stateInfoEnter = stateInfo.enter().append("text") .attr("transform", "translate(-60, 60)") .attr("id", this.node_id++) .attr("class", "stateInfo"); var stateInfoText = stateInfo.selectAll("tspan") .data(function(d) {return JSON.stringify(d, null, 2).split("\n")}); var stateInfoTextEnter = stateInfoText.enter().append("tspan") .attr("x", "0.0") .attr("dy", "1.4em") .attr("xml:space", "preserve") .text(function(d) {return d}); } }; // User defined method Visualizer.prototype.visualize_breakpoints = function() { if (this.visualized_simulator == "PYDEVS") { for (idx in this.breakpoints) { var curr_bp = this.breakpoints[idx]; if (curr_bp.triggered) { this.visualize_messages(curr_bp.outbag, 'outmessage'); for (var key in curr_bp.inbags) { if (curr_bp.inbags[key].length == 2) { curr_bp.inbags[key] = [curr_bp.inbags[key][1]]; } } this.visualize_messages(curr_bp.inbags, 'inmessage'); this.visualize_transitioning(curr_bp.transitioned); } } } var curr_bps = this.breakpoint_infos.selectAll("div").data(this.breakpoints) curr_bps_enter = curr_bps.enter().append("div") .attr("id", function(d) {return "breakpoint_" + d.name}) .attr("class", "breakpoint") .style("transform", function(d, i) {return "translate(" + i * 5 + "px, -8px)"}) .style("float", "left"); curr_bps_enter.append("text") .text(function(d) {return d.name}) .on("click", function(d) { d.enabled = !d.enabled; the_controller.addInput(new Event("toggle_breakpoint", "ui_input", [d.name, d.enabled]), 0.0); }) .on('mouseover', function() { d3.event.preventDefault(); }); curr_bps_enter.append("img") .attr('src', 'img/delete-bp.png') .style('transform', 'translate(1px, 2px)') .on("click", function(d) { the_controller.addInput(new Event("del_breakpoint", "ui_input", [d.name]), 0.0); }); curr_bps.exit().remove(); curr_bps.style("background-color", function(d) { if (d.triggered) { d.triggered = false; if (d.disable_on_trigger) { d.enabled = false; } return "red"; } else { return "transparent"; }}); curr_bps.select("text").style("opacity", function(d) {if (d.enabled) return "1"; else return "0.5";}); }; // Statechart enter/exit action method(s) : Visualizer.prototype.enter_Root_initializing = function() { this.current_state[this.Root].push(this.Root_initializing); }; Visualizer.prototype.exit_Root_initializing = function() { this.current_state[this.Root] = new Array(); }; Visualizer.prototype.enter_Root_running = function() { this.current_state[this.Root].push(this.Root_running); }; Visualizer.prototype.exit_Root_running = function() { this.current_state[this.Root] = new Array(); }; // Statechart transitions : Visualizer.prototype.transition_Root = function(event) { var catched = false; if (!catched) { if (this.current_state[this.Root][0] === this.Root_initializing) { catched = this.transition_Root_initializing(event); } else if (this.current_state[this.Root][0] === this.Root_running) { catched = this.transition_Root_running(event); } } return catched; }; Visualizer.prototype.transition_Root_initializing = function(event) { var catched = false; var enableds = new Array(); enableds.push(1); if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_initializing. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { this.exit_Root_initializing(); this.controller.outputEvent(new Event("reset", "output", [])); this.enter_Root_running(); } catched = true; } return catched; }; Visualizer.prototype.transition_Root_running = function(event) { var catched = false; var enableds = new Array(); if (event.name === "all_states_reset" && event.port === "simulation_input") { enableds.push(1); } if (event.name === "all_states" && event.port === "simulation_input") { enableds.push(2); } if (event.name === "new_states" && event.port === "simulation_input") { enableds.push(3); } if (event.name === "imminents" && event.port === "simulation_input") { enableds.push(4); } if (event.name === "selected_imminent" && event.port === "simulation_input") { enableds.push(5); } if (event.name === "outbag" && event.port === "simulation_input") { enableds.push(6); } if (event.name === "inbags" && event.port === "simulation_input") { enableds.push(7); } if (event.name === "transitioning" && event.port === "simulation_input") { enableds.push(8); } if (event.name === "new_internal_states" && event.port === "simulation_input") { enableds.push(9); } if (event.name === "new_tn" && event.port === "simulation_input") { enableds.push(10); } if (event.name === "structural_changes" && event.port === "simulation_input") { enableds.push(11); } if (event.name === "select_instance" && event.port === "ui_input") { enableds.push(12); } if (event.name === "process_god_event" && event.port === "ui_input") { enableds.push(13); } if (event.name === "god_event_ok" && event.port === "simulation_input") { enableds.push(14); } if (event.name === "inject_event" && event.port === "ui_input") { enableds.push(15); } if (event.name === "inject_ok" && event.port === "simulation_input") { enableds.push(16); } if (event.name === "add_breakpoint" && event.port === "ui_input") { enableds.push(17); } if (event.name === "toggle_breakpoint" && event.port === "ui_input") { enableds.push(18); } if (event.name === "del_breakpoint" && event.port === "ui_input") { enableds.push(19); } if (event.name === "breakpoint_triggered" && event.port === "simulation_input") { enableds.push(20); } if (enableds.length > 1) { console.log("Runtime warning : indeterminism detected in a transition from node Root_running. Only the first in document order enabled transition is executed.") } if (enableds.length > 0) { var enabled = enableds[0]; if (enabled === 1) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.data = []; this.port_connections = []; this.update_vis(the_parameters[2]); this.visualize_initial_state(the_parameters[1]); this.breakpoints = the_parameters[3]; this.visualize_breakpoints(); this.enter_Root_running(); } else if (enabled === 2) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); if (this.visualized_simulator == "NETLOGO") { this.simulation_time.text("SIMULATION TIME: " + the_parameters[0]); this.update_vis(the_parameters[2]); this.visualize_initial_state(the_parameters[1]); this.visualize_breakpoints(); } else { this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.update_vis(the_parameters[2]); this.visualize_initial_state(the_parameters[1]); this.visualize_breakpoints(); } this.enter_Root_running(); } else if (enabled === 3) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.update_vis(the_parameters[3]); this.visualize_new_state(the_parameters[1], the_parameters[2]); this.visualize_breakpoints(); this.enter_Root_running(); } else if (enabled === 4) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.visualize_breakpoints(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.visualize_imminents(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 5) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.visualize_selected_imminent(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 6) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); d3.select("#smallStepInfo_2").classed("inactive", false); d3.selectAll("g.node").classed("imminent", false); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.visualize_messages(the_parameters[1], 'outmessage'); this.enter_Root_running(); } else if (enabled === 7) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.visualize_inbags(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 8) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); d3.select("#smallStepInfo_4").classed("inactive", false); d3.selectAll(".portConnection").classed("invisibleLink", true); d3.selectAll(".port").classed("visible", false); d3.selectAll(".port").classed("invisible", true); d3.selectAll("circle.inmessage").data([]).exit().remove(); d3.selectAll("circle.outmessage").data([]).exit().remove(); this.visualize_transitioning(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 9) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.handle_internal_state_change(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 10) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.visualize_new_tn(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 11) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.simulation_time.text("SIMULATION TIME: " + the_parameters[0][0] + "/" + the_parameters[0][1]); this.update_vis(the_parameters[1]); this.enter_Root_running(); } else if (enabled === 12) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.select_instance(the_parameters); this.enter_Root_running(); } else if (enabled === 13) { this.exit_Root_running(); this.controller.outputEvent(new Event("god_event", "output", [god_event_to_process])); this.enter_Root_running(); } else if (enabled === 14) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); this.handle_internal_state_change(the_parameters[0]); this.enter_Root_running(); } else if (enabled === 15) { this.exit_Root_running(); this.controller.outputEvent(new Event("inject", "output", [event_to_inject])); this.enter_Root_running(); } else if (enabled === 16) { this.exit_Root_running(); this.enter_Root_running(); } else if (enabled === 17) { this.exit_Root_running(); this.controller.outputEvent(new Event("add_breakpoint", "output", [breakpoint_to_add])); this.breakpoints.push({'name': breakpoint_to_add[0], 'enabled': breakpoint_to_add[2], 'disable_on_trigger': breakpoint_to_add[3], 'triggered': false}); this.visualize_breakpoints(); this.enter_Root_running(); } else if (enabled === 18) { var parameters = event.parameters; var breakpoint_id = parameters[0]; var enabled = parameters[1]; this.exit_Root_running(); this.controller.outputEvent(new Event("toggle_breakpoint", "output", [breakpoint_id,enabled])); this.visualize_breakpoints(); this.enter_Root_running(); } else if (enabled === 19) { var parameters = event.parameters; var breakpoint_id = parameters[0]; this.exit_Root_running(); this.controller.outputEvent(new Event("del_breakpoint", "output", [breakpoint_id])); this.breakpoints = this.breakpoints.filter(function(bp) {return bp.name != breakpoint_id}); this.visualize_breakpoints(); this.enter_Root_running(); } else if (enabled === 20) { var parameters = event.parameters; var the_parameters = parameters[0]; this.exit_Root_running(); for (var idx in this.breakpoints) { var curr_bp = this.breakpoints[idx]; if (curr_bp.name == the_parameters[0]) { curr_bp.triggered = true; curr_bp.transitioned = the_parameters[1]; curr_bp.outbag = the_parameters[2]; curr_bp.inbags = the_parameters[3]; } } this.visualize_breakpoints() this.enter_Root_running(); } catched = true; } return catched; }; // Execute transitions Visualizer.prototype.transition = function(event) { if (!event) event = new Event(); this.state_changed = this.transition_Root(event); }; // inState method for statechart Visualizer.prototype.inState = function(nodes) { for (var c in this.current_state) { if (!this.current_state.hasOwnProperty(c)) continue; var new_nodes = new Array(); for (var n in nodes) { if (!nodes.hasOwnProperty(n)) continue; if (this.current_state[c].indexOf(nodes[n]) === -1) { new_nodes.push(nodes[n]); } } nodes = new_nodes; if (nodes.length === 0) { return true; } } return false; }; Visualizer.prototype.commonConstructor = function(controller) { if (!controller) controller = null; // Constructor part that is common for all constructors. RuntimeClassBase.call(this); // User defined input ports this.inports = new Object(); this.controller = controller; this.object_manager = (controller == null ? null : controller.object_manager); this.current_state = new Object(); this.history_state = new Object(); // Initialize statechart this.current_state[this.Root] = new Array(); }; Visualizer.prototype.start = function() { RuntimeClassBase.prototype.start.call(this); this.enter_Root_initializing(); }; // put class in global diagram object DebuggingEnvironment.Visualizer = Visualizer; var ObjectManager = function(controller) { ObjectManagerBase.call(this, controller); }; ObjectManager.prototype = new ObjectManagerBase(); ObjectManager.prototype.instantiate = function(class_name, construct_params) { if (class_name === "MainApp") { var instance = new MainApp(this.controller); instance.associations = new Object(); instance.associations["toolbar"] = new Association("DebuggingToolbar", 1, 1); instance.associations["visualizer"] = new Association("Visualizer", 1, 1); } else if (class_name === "DebuggingToolbar") { var instance = new DebuggingToolbar(this.controller); instance.associations = new Object(); instance.associations["parent"] = new Association("MainApp", 1, 1); instance.associations["buttons"] = new Association("Button", 0, -1); } else if (class_name === "Button") { var instance = new Button(this.controller, construct_params[0], construct_params[1], construct_params[2]); instance.associations = new Object(); instance.associations["parent"] = new Association("DebuggingToolbar", 1, 1); } else if (class_name === "Visualizer") { var instance = new Visualizer(this.controller); instance.associations = new Object(); instance.associations["parent"] = new Association("MainApp", 1, 1); } return instance; }; // put in global diagram object DebuggingEnvironment.ObjectManager = ObjectManager; var Controller = function(keep_running, finished_callback) { if (keep_running === undefined) keep_running = true; JsEventLoopControllerBase.call(this, new ObjectManager(this), keep_running, finished_callback); this.addInputPort("ui_input"); this.addInputPort("simulation_input"); this.addOutputPort("output"); this.object_manager.createInstance("MainApp", []); }; Controller.prototype = new JsEventLoopControllerBase(); // put in global diagram object DebuggingEnvironment.Controller = Controller; })();