# cpy Thonny - guizero shuttle simulation - signal patterns
# provided by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-01-03  initial release

# tools |  manage packages | guizero : search on pypi | install
# drawing: https://lawsie.github.io/guizero/drawing/

import	time
from 	guizero import App, Drawing

# ==================== GUI setup =========================

app = App('Shuttle simulation', width=800, height=200)
ctx = Drawing(app, width='fill', height='fill')

# ======================= Globals ========================

signal_patterns = [['r', 'r', 'r',  'r', 'r', 'r'],
                   ['g', 'g', 'g',  'r', 'r', 'r'],
                   ['r', 'g', 'g',  'r', 'r', 'r'],
                   ['r', 'r', 'g',  'r', 'r', 'r'],
                   ['r', 'r', 'r',  'r', 'r', 'r'],
                   ['r', 'r', 'r',  'g', 'g', 'g'],
                   ['r', 'r', 'r',  'g', 'g', 'r'],
                   ['r', 'r', 'r',  'g', 'r', 'r']]

# ======================= Widgets ========================

# draw track, center @ x=400, y=100
def track():
    ctx.line(10,  90, 790,  90, width=4)
    ctx.line(10, 110, 790, 110, width=4)


# draw train at position x
def train(x=0):
    x0 = 60; y0 = 100
    ctx.rectangle(x0+x-40, y0-20, x0+x+40, y0+20, color='blue')


# draw 2 aspect signal, centre at x, y
def aspect2(x=0, y=0, green=False, mirror=False):
    x0 = 400+x; y0=100+y
    m  = -1 if mirror else +1
    ctx.line     (x0-m*30, y0-2,  x0-m*10, y0-2,  width=2)
    ctx.line     (x0-m*30, y0+2,  x0-m*10, y0+2,  width=2)
    ctx.line     (x0-m*30, y0-10, x0-m*30, y0+10, width=5)
    ctx.rectangle(x0-m*10, y0-10, x0+m*30, y0+10, color='black')
    if green: ctx.oval(x0+m*14, y0-6, x0+m*26, y0+6, color='lime')
    else    : ctx.oval(x0-m*6,  y0-6, x0+m*6,  y0+6, color='red')


# set 6 signals according to pattern
def setSignals(pattern=['r', 'r', 'r',  'g', 'r', 'r']):
    for pos, idx in zip((-250, 0, 250), ((0, 3), (1, 4), (2, 5))):
        aspect2(x=pos, y=-40, green=pattern[idx[0]]=='g')
        aspect2(x=pos, y= 40, green=pattern[idx[1]]=='g', mirror=True)


# draw layout:  signals[state], track and train
def layout(pos=0, state=0):
    pattern = signal_patterns[state]
    ctx.clear()					# clear context
    track()
    train(pos)
    setSignals(pattern)
    
# ======================= Timer =========================

train_pos  = 0
train_step = 4
state      = 0
# application sequencer
def onTimer():
    global train_pos, train_step, state
 
    if train_pos == 0:
        state = 1
        train_step = 4
    elif train_pos == 100:
        state = 2 if train_step > 0 else 0
    elif train_pos == 360:
        state = 3 if train_step > 0 else 7
    elif train_pos == 600:
        state = 4 if train_step > 0 else 6
    elif train_pos == 680:
        state = 5
        train_step = -4
    layout(train_pos, state)
    train_pos += train_step

# ========================= main =========================

layout()
ctx.repeat(50, onTimer)			# sequencer @ 2 Sec
app.display()						# start GUI loop
    
# ========================== end =========================    
