enigma_machine_w_gui.py

#!/usr/bin/python3
# ===================================================================
# Enigma machine simulation and a GUI
# ===================================================================

from enigma_gui import enigma_gui
from EnigmaConfig import EnigmaConfig
from EnigmaMachine import EnigmaMachine
import PySimpleGUI as sg
import os
import re
import sys

# -------------------------------------------------------------------
# ---- configuration
# -------------------------------------------------------------------

# ---- get configuration file

configfile = 'enigma_config.csv'

if len(sys.argv) > 1:
     configfile = sys.argv[1]

if not os.path.exists(configfile):
    print()
    print(f'Can not find enigma configuration file ({configfile})') 
    print()
    sys.exit()

# ---- create an enigma machine object

em = EnigmaMachine(configfile)

# ---- create a GUI window

win,tsize = enigma_gui(em.config)

# -------------------------------------------------------------------
# ----event loop 
# -------------------------------------------------------------------

# ---- alphabet to index support function

def _char_to_idx(c,abc):
    for i in range(len(abc)):
        if abc[i] == c:
            return i
    return 0


lst_in  = ''
lst_out = ''

while(True):

    # ---- wait on an event

    event,values = win.read()

    ##print()
    ##print(f'event = {event}')
    ##print(f'values= {values}')
    ##print()

    # ---- event: exit program

    if event in ('Exit',sg.WIN_CLOSED):
        break

    # ---- event: single character

    if len(event) == 1:
        if event not in em.config.abc:
            print()
            print('internal error - do not recognize event ' +
                 f'({event}) - end program')
            print()
            sys.exit()

        lst_in = lst_in + event
        if len(lst_in) > tsize-1:
            win['-IN-'].update('text buffer overflow')
            win['-OUT-'].update('text buffer overflow')
            continue
        win['-IN-'].update(lst_in)

        idx_in = em.char_to_idx(event)
        idx_out = em.substitution(idx_in)
        lst_out = lst_out + em.idx_to_char(idx_out)
        win['-OUT-'].update(lst_out)

        continue

    # ---- event: reset rotors

    if event == 'Reset Rotors':
        lst_in  = ''
        lst_out = ''
        win['-IN-'].update('')
        win['-OUT-'].update('')
        em.reset()
        continue

    # ---- set rotors

    if event == 'Set Rotors':
 
        lst_in  = ''
        lst_out = ''
        win['-IN-'].update('')
        win['-OUT-'].update('')

        rnam = values['-RROTOR-']
        rpos = values['-RPOSITION-'].upper()
        ridx = _char_to_idx(rpos,em.abc)

        mnam = values['-MROTOR-']
        mpos = values['-MPOSITION-'].upper()
        midx = _char_to_idx(mpos,em.abc)

        lnam = values['-LROTOR-']
        lpos = values['-LPOSITION-'].upper()
        lidx = _char_to_idx(lpos,em.abc)

        nam = [lnam,mnam,rnam]
        pos = [lidx,midx,ridx]
        em.set(nam,pos)
        continue


    # ---- event: clear encrypt/decrypt buffers

    if event == 'Clear Buffer':
        lst_in  = ''
        lst_out = ''
        win['-IN-'].update('')
        win['-OUT-'].update('')
        continue

    # ---- event: display (enigma machine internals)

    if event == 'Display':
        em.display_internal_state()
        continue

    # ---- event: stats (enigma machine rotor info) 

    if event == 'Stats':
        em.display_rotor_stats()
        continue

    # ---- event: auto advance on

    if event == 'Auto Advance On':
        em.auto_advance_on()
        continue

    # ---- event: auto advance off

    if event == 'Auto Advance Off':
        em.auto_advance_off()
        continue

    # ---- event: substitution debug on

    if event == 'Sub Debug On':
        em.sub_debug_on()
        continue

    # ---- event: substitution debug off

    if event == 'Sub Debug Off':
        em.sub_debug_off()
        continue

win.close()
print()