diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9af86e --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +Starting point for the Statecharts assignment of MoSIS in the academic year 2024-2025. + +Clone this repository, and import the `StartingPoint` directory as an Itemis CREATE project (without copying the files). This way, you can still do a `git pull` in case of a bug fix in the Python code. + + +## Dependencies + +To run the Python scripts, you need the following: + + - **Python 3.?** (tested with 3.12) + - **TkInter** library (included in most Python distributions) + + +## Contents + +### Exercises + +Files related to the exercises: + - **`StartingPoint/exercises/`**: (DO NOT EDIT) directory that contains the exercises. Each exercise is a Statechart model that you can run/debug in ITEMIS. + - **`StartingPoint/runner_exercises_tests.py`**: (FEEL FREE TO EDIT) runs automated tests on (generated code from) the exercise models. Feel free to edit and run this file to understand the exercises better. + +### Assignment + +Files related to the assignment: + - **`StartingPoint/Statechart.ysc`**: (MUST EDIT THIS) this is the Statechart model. + - **`StartingPoint/runner_tests.py`**: (ADD ONE TEST) runs automated tests on your Statechart. It already includes 3 test scenarios, which your solution **must pass**! You are not allowed to modify the existing tests. You must however **add one test** to it. + - **`StartingPoint/runner_gui.py`**: (DO NOT EDIT) this script runs a TkInter GUI that allows you to interact with your Statechart. + +When running the GUI, you can pass an additional `time_scale` parameter, as such: +``` +cd StartingPoint +python runner_gui.py 0.5 +``` +This will run the simulation at half-speed. + +### Background + +Other files: + - **`StartingPoint/PythonGenerator.sgen`**: (DO NOT EDIT) specifies how ITEMIS should generate Python code from the models. + - **`StartingPoint/srcgen/`**: (DO NOT EDIT BY HAND) This directory contains Python code generated from the models. Each time you change a model, code will be re-generated, overwriting the files in this directory. + - **`StartingPoint/lib/`**: (DO NOT EDIT) A Statecharts run-time library, for running the generated code in (scaled) real-time while integrating with TkInter's event loop (for the GUI), and for running the Python tests (simulating as-fast-as-possible). diff --git a/StartingPoint/lib/test.py b/StartingPoint/lib/test.py index 9401273..c771ceb 100644 --- a/StartingPoint/lib/test.py +++ b/StartingPoint/lib/test.py @@ -134,3 +134,14 @@ def run_scenario(input_trace, expected_output_trace, statechart_class, INITIAL, elif verbose: print_diff() return True + +def run_scenarios(scenarios, statechart_class, initial, idempotent, verbose=True): + ok = True + for scenario in scenarios: + print(f"Running scenario: {scenario["name"]}") + ok = run_scenario(scenario["input_events"], scenario["output_events"], statechart_class, initial, idempotent, verbose=verbose) and ok + print("--------") + if ok: + print("All scenarios passed.") + else: + print("Some scenarios failed.") diff --git a/StartingPoint/runner_exercises_tests.py b/StartingPoint/runner_exercises_tests.py new file mode 100644 index 0000000..e5f324f --- /dev/null +++ b/StartingPoint/runner_exercises_tests.py @@ -0,0 +1,63 @@ +from srcgen import a, b, c, d, e +from lib.test import run_scenarios + +SCENARIOS_A = [ + { + "name": "A", + "input_events": [], + "output_events": [ + (1000000000, "x", None), + (2000000000, "x", None), + (3000000000, "x", None), + ], + }, +] +SCENARIOS_B = [ + { + "name": "B", + "input_events": [], + "output_events": [ + (2000000000, "inner", None), + (3000000000, "outer", None), + (5000000000, "inner", None), + (6000000000, "outer", None), + (8000000000, "inner", None), + (9000000000, "outer", None), + ], + }, +] +SCENARIOS_C = [ + { + "name": "C", + "input_events": [], + "output_events": [], + }, +] +SCENARIOS_D = [ + { + "name": "D", + "input_events": [], + "output_events": [], + }, +] +SCENARIOS_E = [ + { + "name": "E", + "input_events": [], + "output_events": [ + (1000000000, "x", None), + (1000000000, "y", None), + (2000000000, "x", None), + (2000000000, "y", None), + (3000000000, "x", None), + (3000000000, "y", None), + ], + }, +] + +if __name__ == "__main__": + run_scenarios(SCENARIOS_A, a.A, [], [], verbose=True) + run_scenarios(SCENARIOS_B, b.B, [], [], verbose=True) + run_scenarios(SCENARIOS_C, c.C, [], [], verbose=True) + run_scenarios(SCENARIOS_D, d.D, [], [], verbose=True) + run_scenarios(SCENARIOS_E, e.E, [], [], verbose=True) diff --git a/StartingPoint/runner_gui.py b/StartingPoint/runner_gui.py index cede20d..46f1bb9 100644 --- a/StartingPoint/runner_gui.py +++ b/StartingPoint/runner_gui.py @@ -1,5 +1,6 @@ import tkinter import atexit +import sys # load generated Statechart code from srcgen.water_level_simulator import WaterLevelSimulator diff --git a/StartingPoint/runner_tests.py b/StartingPoint/runner_tests.py index fd8c34a..7b50f84 100644 --- a/StartingPoint/runner_tests.py +++ b/StartingPoint/runner_tests.py @@ -1,5 +1,5 @@ import functools -from lib.test import run_scenario +from lib.test import run_scenarios # from srcgen.lock_controller import LockController from srcgen.solution import Solution as LockController # Teacher's solution @@ -229,12 +229,4 @@ INITIAL = [ ] if __name__ == "__main__": - ok = True - for scenario in SCENARIOS: - print(f"Running scenario: {scenario["name"]}") - ok = run_scenario(scenario["input_events"], scenario["output_events"], LockController, INITIAL, IDEMPOTENT, verbose=False) and ok - print("--------") - if ok: - print("All scenarios passed.") - else: - print("Some scenarios failed.") + run_scenarios(SCENARIOS, LockController, INITIAL, IDEMPOTENT)