mosis24Statecharts/StartingPoint/runner_gui.py
2024-11-28 23:47:19 +01:00

83 lines
3.3 KiB
Python

import tkinter
import atexit
# load generated Statechart code
from srcgen.water_level_simulator import WaterLevelSimulator
# from srcgen.lock_controller import LockController
from srcgen.solution import Solution as LockController # Teacher's solution
from lib.yakindu.rx import Observer
from lib.controller import Controller, pretty_time
from lib.tracer import Tracer, format_trace_as_python_code
from lib.yakindu_helpers import YakinduTimerServiceAdapter, CallbackObserver, trace_output_events
from lib.realtime.realtime import WallClock
from lib.realtime.event_loop import EventLoopRealTimeSimulation
from lib.realtime.tk_event_loop import TkEventLoopAdapter
from gui import GUI
if __name__ == "__main__":
# read time scale from command line
try:
time_scale = float(sys.argv[1])
except:
time_scale = 1.0
print(f"TIME SCALE is {time_scale}")
sc = LockController()
wlvlsc = WaterLevelSimulator() # our environment is also modeled as a statechart :)
controller = Controller()
# We'll record input and output events
tracer = Tracer()
controller.input_tracers.append((sc, tracer.record_input_event))
trace_output_events(controller, sc, callback=tracer.record_output_event)
sc.timer_service = YakinduTimerServiceAdapter(controller)
wlvlsc.timer_service = YakinduTimerServiceAdapter(controller)
toplevel = tkinter.Tk()
wall_clock = WallClock(time_scale)
sim = EventLoopRealTimeSimulation(controller, TkEventLoopAdapter(toplevel), wall_clock)
gui = GUI(sim, sc, wlvlsc, toplevel)
sim.time_advance_callback = gui.time_changed
# output event handlers of LockController
sc.set_request_pending_observable.subscribe(CallbackObserver(gui.set_request_pending))
sc.open_flow_observable.subscribe(CallbackObserver(lambda side: gui.set_flow(side, True)))
sc.close_flow_observable.subscribe(CallbackObserver(lambda side: gui.set_flow(side, False)))
sc.open_doors_observable.subscribe(CallbackObserver(lambda side: gui.set_doors(side, True)))
sc.close_doors_observable.subscribe(CallbackObserver(lambda side: gui.set_doors(side, False)))
sc.green_light_observable.subscribe(CallbackObserver(gui.set_green_light))
sc.red_light_observable.subscribe(CallbackObserver(gui.set_red_light))
sc.set_sensor_broken_observable.subscribe(CallbackObserver(gui.set_sensor_broken))
# output event handlers of WaterLevelSimulator
wlvlsc.sensor_reading_observable.subscribe(CallbackObserver(gui.on_water_level_reading))
wlvlsc.real_water_level_observable.subscribe(CallbackObserver(gui.on_real_water_level))
def print_trace_on_exit():
print("End of simulation. Full I/O trace:")
print("{")
print(' "name": "interactive",')
print(' "input_events": ', end='')
print(format_trace_as_python_code(tracer.input_events, indent=4))
print(' "output_events": ', end='')
print(format_trace_as_python_code(tracer.output_events, indent=4))
print("}")
atexit.register(print_trace_on_exit)
wall_clock.record_start_time() # start_time is NOW!
# Enter default states
sc.enter()
wlvlsc.enter()
sim.poke() # schedule first simulator wakeup (in tk event loop)
toplevel.mainloop() # everything is controlled by tkinter's eventloop