Compare commits

..

10 Commits

Author SHA1 Message Date
dee45e5eae Expand lines 2026-03-04 17:31:14 -07:00
eaaa8e5f57 Ignore aider 2026-03-04 17:31:06 -07:00
a19aec1848 refactor: Expand single-line statements for improved readability
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 17:27:17 -07:00
af6072627e fix: Clear screen after printing labels and forum searches
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 17:20:11 -07:00
339a58e1bf Fix: Ensure accurate typing state and simplify entry key check
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 17:13:25 -07:00
3fc74d82ad fix: Prevent typing debounce on Nametag and Label screens
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 17:10:11 -07:00
17e3ad347a fix: Disable key debounce for text input entry and typing
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 17:03:58 -07:00
c58a356c02 fix: Clear line artifacts in Nametag, Label, Message, and Think screens
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 16:47:49 -07:00
d8886e80db chore: Add logging import statement 2026-03-04 16:47:47 -07:00
fdfefffda6 fix: Prevent key buffering during rate limiting
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-03-04 16:37:38 -07:00
3 changed files with 389 additions and 135 deletions

1
.gitignore vendored
View File

@@ -115,3 +115,4 @@ venv.bak/
secrets.py
tmp.png
.aider*

11
main.py
View File

@@ -43,15 +43,16 @@ def main_loop(stdscr):
logging.info('Starting main loop...')
while True:
# Rate limit key presses unless in a text input field
if not screens[state.current_screen].is_typing and time.time() < state.last_key_time + 1:
time.sleep(0.05)
else:
c = stdscr.getch()
if c != curses.ERR:
current_screen = screens[state.current_screen]
# Rate limit key presses unless in a text input field
if not current_screen.is_typing and not current_screen.is_entry_key(c) and time.time() < state.last_key_time + 1:
pass # Key press ignored due to rate limit
else:
state.c = c
state.last_key_time = time.time()
screens[state.current_screen].handle_input(c)
current_screen.handle_input(c)
if state.current_screen != state.prev_screen:
logging.info('Switching to screen: %s', state.current_screen)

508
tui.py
View File

@@ -3,6 +3,7 @@ import time
import textwrap
import random
import os
import logging
from datetime import datetime, timezone
import utils
@@ -43,6 +44,9 @@ class Screen:
except:
return None
def is_entry_key(self, c):
return False
def try_highlight(self, c):
if c and time.time() - self.state.highlight_debounce > 0.6:
self.state.highlight_debounce = time.time()
@@ -123,22 +127,38 @@ class HomeScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 's': self.state.current_screen = 'stats'
elif button == 'i': self.state.current_screen = 'info'
elif button == 'n': self.state.current_screen = 'nametag'
elif button == 'l': self.state.current_screen = 'label'
elif button == 'z': self.state.current_screen = 'games'
elif button == '0': self.state.current_screen = 'asimov'
elif button == 'g': self.state.current_screen = 'sign'
elif button == 'v': self.state.current_screen = 'protovac_sign'
elif button == 'r': self.state.current_screen = 'train'
elif button == 'c': self.state.current_screen = 'classes'
elif button == 'm' and utils.openai_key: self.state.current_screen = 'message'
elif button == 't' and utils.wa_api_key: self.state.current_screen = 'think'
elif c == 68: self.state.current_screen = 'debug'
elif button == 'a': self.state.current_screen = 'about'
elif button == 'p': self.state.current_screen = 'protocoin'
else: self.try_highlight(c)
if button == 's':
self.state.current_screen = 'stats'
elif button == 'i':
self.state.current_screen = 'info'
elif button == 'n':
self.state.current_screen = 'nametag'
elif button == 'l':
self.state.current_screen = 'label'
elif button == 'z':
self.state.current_screen = 'games'
elif button == '0':
self.state.current_screen = 'asimov'
elif button == 'g':
self.state.current_screen = 'sign'
elif button == 'v':
self.state.current_screen = 'protovac_sign'
elif button == 'r':
self.state.current_screen = 'train'
elif button == 'c':
self.state.current_screen = 'classes'
elif button == 'm' and utils.openai_key:
self.state.current_screen = 'message'
elif button == 't' and utils.wa_api_key:
self.state.current_screen = 'think'
elif c == 68:
self.state.current_screen = 'debug'
elif button == 'a':
self.state.current_screen = 'about'
elif button == 'p':
self.state.current_screen = 'protocoin'
else:
self.try_highlight(c)
class DebugScreen(Screen):
@@ -153,8 +173,10 @@ class DebugScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif c == 88: exit()
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif c == 88:
exit()
elif c == 83:
curses.nocbreak()
self.stdscr.keypad(False)
@@ -171,7 +193,8 @@ class DebugScreen(Screen):
logging.info('Spawning nethack.')
os.system('/usr/games/nethack')
exit()
else: self.try_highlight(c)
else:
self.try_highlight(c)
class StatsScreen(Screen):
@@ -206,8 +229,10 @@ class StatsScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
else: self.try_highlight(c)
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
else:
self.try_highlight(c)
class ClassesScreen(Screen):
@@ -251,7 +276,8 @@ class ClassesScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
if self.classes and self.classes_start+6 < len(self.classes):
self.classes_start += 6
@@ -260,7 +286,8 @@ class ClassesScreen(Screen):
if self.classes_start > 0:
self.classes_start -= 6
self.stdscr.erase()
else: self.try_highlight(c)
else:
self.try_highlight(c)
class TextScreen(Screen):
def __init__(self, state, stdscr, title, text_content):
@@ -283,7 +310,8 @@ class TextScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
if self.text_line+19 < len(self.lines):
self.text_line += 19
@@ -292,7 +320,8 @@ class TextScreen(Screen):
if self.text_line > 0:
self.text_line -= 19
self.stdscr.erase()
else: self.try_highlight(c)
else:
self.try_highlight(c)
class ProtocoinScreen(Screen):
def __init__(self, state, stdscr):
@@ -334,7 +363,8 @@ class ProtocoinScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'j' or c == curses.KEY_DOWN or c == KEY_SPACE:
if self.protocoin and self.protocoin_line+19 < len(self.protocoin['transactions']):
self.protocoin_line += 19
@@ -343,7 +373,8 @@ class ProtocoinScreen(Screen):
if self.protocoin_line > 0:
self.protocoin_line -= 19
self.stdscr.erase()
else: self.try_highlight(c)
else:
self.try_highlight(c)
class SignScreen(Screen):
def __init__(self, state, stdscr):
@@ -387,11 +418,17 @@ class SignScreen(Screen):
self.sign_to_send = ''
else:
self.sign_to_send = self.handle_text_input(c, self.sign_to_send)
elif button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'e':
self.is_typing = True
self.sign_to_send = '_'
else: self.try_highlight(c)
else:
self.try_highlight(c)
def is_entry_key(self, c):
button = self.get_button(c)
return not self.is_typing and button == 'e'
class ProtovacSignScreen(Screen):
def draw(self):
@@ -419,20 +456,34 @@ class ProtovacSignScreen(Screen):
def handle_input(self, c):
res = ''
button = self.get_button(c)
if button == '1': res = utils.protovac_sign_color([255,255,255])
elif button == '2': res = utils.protovac_sign_color([255,150,150])
elif button == '3': res = utils.protovac_sign_color([150,255,150])
elif button == '4': res = utils.protovac_sign_color([150,150,255])
elif button == '5': res = utils.protovac_sign_color([255,50,255])
elif button == '6': res = utils.protovac_sign_color([random.randint(50,255),random.randint(50,255),random.randint(50,255)])
elif button == 'q': res = utils.protovac_sign_effect(0)
elif button == 'w': res = utils.protovac_sign_effect(2)
elif button == 'e': res = utils.protovac_sign_effect(49)
elif button == 'r': res = utils.protovac_sign_effect(90)
elif button == 't': res = utils.protovac_sign_effect(89)
elif button == 'y': res = utils.protovac_sign_effect(random.randint(3,90))
elif button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
else: self.try_highlight(c)
if button == '1':
res = utils.protovac_sign_color([255,255,255])
elif button == '2':
res = utils.protovac_sign_color([255,150,150])
elif button == '3':
res = utils.protovac_sign_color([150,255,150])
elif button == '4':
res = utils.protovac_sign_color([150,150,255])
elif button == '5':
res = utils.protovac_sign_color([255,50,255])
elif button == '6':
res = utils.protovac_sign_color([random.randint(50,255),random.randint(50,255),random.randint(50,255)])
elif button == 'q':
res = utils.protovac_sign_effect(0)
elif button == 'w':
res = utils.protovac_sign_effect(2)
elif button == 'e':
res = utils.protovac_sign_effect(49)
elif button == 'r':
res = utils.protovac_sign_effect(90)
elif button == 't':
res = utils.protovac_sign_effect(89)
elif button == 'y':
res = utils.protovac_sign_effect(random.randint(3,90))
elif button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
else:
self.try_highlight(c)
if res == 'Error':
self.stdscr.addstr(21, 12, 'ERROR')
@@ -491,21 +542,30 @@ class NametagScreen(Screen):
if self.nametag_member:
self.stdscr.addstr(8, 4, 'Enter your name: ' + self.nametag_member)
self.stdscr.clrtoeol()
self.stdscr.move(10, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Print [ESC] Cancel')
elif self.nametag_guest:
self.stdscr.move(8, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(10, 4, 'Enter your name: ' + self.nametag_guest)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Print [ESC] Cancel')
else:
self.stdscr.addstr(8, 4, '[M] Member nametag', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(10, 4, '[G] Guest nametag', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
def handle_input(self, c):
button = self.get_button(c)
if self.nametag_member:
self.is_typing = True
if c == KEY_ESCAPE: self.nametag_member = ''
if c == KEY_ESCAPE:
self.nametag_member = ''
self.is_typing = False
elif c == KEY_ENTER:
if len(self.nametag_member) > 1:
self.stdscr.addstr(15, 4, 'Printing...')
@@ -513,10 +573,12 @@ class NametagScreen(Screen):
utils.print_nametag(self.nametag_member[:-1], guest=False)
self.nametag_member = ''
self.state.current_screen = 'home'
else: self.nametag_member = self.handle_text_input(c, self.nametag_member)
else:
self.nametag_member = self.handle_text_input(c, self.nametag_member)
elif self.nametag_guest:
self.is_typing = True
if c == KEY_ESCAPE: self.nametag_guest = ''
if c == KEY_ESCAPE:
self.nametag_guest = ''
self.is_typing = False
elif c == KEY_ENTER:
if len(self.nametag_guest) > 1:
self.stdscr.addstr(15, 4, 'Printing...')
@@ -524,13 +586,24 @@ class NametagScreen(Screen):
utils.print_nametag(self.nametag_guest[:-1], guest=True)
self.nametag_guest = ''
self.state.current_screen = 'home'
else: self.nametag_guest = self.handle_text_input(c, self.nametag_guest)
else:
self.nametag_guest = self.handle_text_input(c, self.nametag_guest)
else:
self.is_typing = False
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif button == 'm': self.nametag_member = '_'
elif button == 'g': self.nametag_guest = '_'
else: self.try_highlight(c)
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'm':
self.nametag_member = '_'
self.is_typing = True
elif button == 'g':
self.nametag_guest = '_'
self.is_typing = True
else:
self.try_highlight(c)
def is_entry_key(self, c):
button = self.get_button(c)
return not self.is_typing and button in ['m', 'g']
class LabelScreen(Screen):
# This screen is complex, breaking it down into sub-states
@@ -568,28 +641,57 @@ class LabelScreen(Screen):
# Drawing logic for different sub-screens
if self.sub_screen == 'menu':
self.stdscr.addstr(8, 4, '[T] Tool label', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(10, 4, '[S] Sheet material', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(12, 4, '[G] Generic label', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(14, 4, '[F] Forum thread', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if self.state.highlight_keys else 0)
elif self.sub_screen == 'tool':
self.stdscr.addstr(8, 4, 'Enter Wiki-ID tool number: ' + self.label_tool)
self.stdscr.clrtoeol()
for i in [10, 12, 14]:
self.stdscr.move(i, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Print [ESC] Cancel')
elif self.sub_screen == 'material_name':
self.stdscr.addstr(10, 4, 'Enter your name: ' + self.label_material_name)
self.stdscr.clrtoeol()
for i in [8, 12, 14]:
self.stdscr.move(i, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Next [ESC] Cancel')
elif self.sub_screen == 'material_contact':
self.stdscr.addstr(10, 4, 'Enter your name: ' + self.label_material_name[:-1])
self.stdscr.clrtoeol()
self.stdscr.addstr(12, 4, 'Enter your contact info: ' + self.label_material_contact)
self.stdscr.clrtoeol()
for i in [8, 14]:
self.stdscr.move(i, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Print [ESC] Cancel')
elif self.sub_screen == 'generic':
self.stdscr.addstr(12, 4, 'Enter your message: ' + self.label_generic)
self.stdscr.clrtoeol()
for i in [8, 10, 14]:
self.stdscr.move(i, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Print [ESC] Cancel')
elif self.sub_screen == 'consumable':
self.stdscr.addstr(12, 4, 'Enter the item: ' + self.label_consumable)
self.stdscr.clrtoeol()
for i in [8, 10, 14]:
self.stdscr.move(i, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Print [ESC] Cancel')
elif self.sub_screen == 'forum_search':
self.stdscr.addstr(14, 4, 'Search for a thread: ' + self.label_forum_search)
self.stdscr.clrtoeol()
for i in [8, 10, 12]:
self.stdscr.move(i, 4)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Search [ESC] Cancel')
elif self.sub_screen == 'forum_results':
if self.search_results is not None:
@@ -608,70 +710,150 @@ class LabelScreen(Screen):
self.is_typing = self.sub_screen not in ['menu', 'forum_results']
if self.sub_screen == 'menu':
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif button == 't': self.sub_screen = 'tool'; self.label_tool = '_'
elif button == 's': self.sub_screen = 'material_name'; self.label_material_name = '_'
elif button == 'g': self.sub_screen = 'generic'; self.label_generic = '_'
elif button == 'c': self.sub_screen = 'consumable'; self.label_consumable = '_'
elif button == 'f': self.sub_screen = 'forum_search'; self.label_forum_search = '_'
else: self.try_highlight(c)
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 't':
self.sub_screen = 'tool'
self.label_tool = '_'
self.is_typing = True
elif button == 's':
self.sub_screen = 'material_name'
self.label_material_name = '_'
self.is_typing = True
elif button == 'g':
self.sub_screen = 'generic'
self.label_generic = '_'
self.is_typing = True
elif button == 'c':
self.sub_screen = 'consumable'
self.label_consumable = '_'
self.is_typing = True
elif button == 'f':
self.sub_screen = 'forum_search'
self.label_forum_search = '_'
self.is_typing = True
else:
self.try_highlight(c)
elif self.sub_screen == 'tool':
if c == KEY_ESCAPE: self.on_enter()
if c == KEY_ESCAPE:
self.on_enter()
self.stdscr.erase()
elif c == KEY_ENTER:
if len(self.label_tool) > 1:
self.stdscr.addstr(15, 4, 'Printing...'); self.stdscr.refresh()
try: utils.print_tool_label(self.label_tool[:-1])
except: self.stdscr.addstr(15, 4, 'Error.'); self.stdscr.refresh(); time.sleep(2)
self.stdscr.addstr(15, 4, 'Printing...')
self.stdscr.refresh()
try:
utils.print_tool_label(self.label_tool[:-1])
except:
self.stdscr.addstr(15, 4, 'Error.')
self.stdscr.refresh()
time.sleep(2)
self.on_enter()
self.stdscr.erase()
elif c <= 57 and c >= 48:
self.label_tool = self.handle_text_input(c, self.label_tool)
elif self.sub_screen == 'material_name':
if c == KEY_ESCAPE: self.on_enter()
if c == KEY_ESCAPE:
self.on_enter()
self.stdscr.erase()
elif c == KEY_ENTER and len(self.label_material_name) > 1:
self.sub_screen = 'material_contact'; self.label_material_contact = '_'
else: self.label_material_name = self.handle_text_input(c, self.label_material_name)
self.sub_screen = 'material_contact'
self.label_material_contact = '_'
else:
self.label_material_name = self.handle_text_input(c, self.label_material_name)
elif self.sub_screen == 'material_contact':
if c == KEY_ESCAPE: self.on_enter()
if c == KEY_ESCAPE:
self.on_enter()
self.stdscr.erase()
elif c == KEY_ENTER and len(self.label_material_contact) > 1:
self.stdscr.addstr(15, 4, 'Printing...'); self.stdscr.refresh()
self.stdscr.addstr(15, 4, 'Printing...')
self.stdscr.refresh()
utils.print_sheet_label(self.label_material_name[:-1], self.label_material_contact[:-1])
self.on_enter()
else: self.label_material_contact = self.handle_text_input(c, self.label_material_contact)
self.stdscr.erase()
else:
self.label_material_contact = self.handle_text_input(c, self.label_material_contact)
elif self.sub_screen == 'generic':
if c == KEY_ESCAPE: self.on_enter()
if c == KEY_ESCAPE:
self.on_enter()
self.stdscr.erase()
elif c == KEY_ENTER and len(self.label_generic) > 1:
self.stdscr.addstr(15, 4, 'Printing...'); self.stdscr.refresh()
try: utils.print_generic_label(self.label_generic[:-1])
except: self.stdscr.addstr(15, 4, 'Error.'); self.stdscr.refresh(); time.sleep(2)
self.stdscr.addstr(15, 4, 'Printing...')
self.stdscr.refresh()
try:
utils.print_generic_label(self.label_generic[:-1])
except:
self.stdscr.addstr(15, 4, 'Error.')
self.stdscr.refresh()
time.sleep(2)
self.on_enter()
else: self.label_generic = self.handle_text_input(c, self.label_generic)
self.stdscr.erase()
else:
self.label_generic = self.handle_text_input(c, self.label_generic)
elif self.sub_screen == 'consumable':
if c == KEY_ESCAPE: self.on_enter()
elif c == KEY_ENTER and len(self.label_consumable) > 1:
self.stdscr.addstr(15, 4, 'Printing...'); self.stdscr.refresh()
try: utils.print_consumable_label(self.label_consumable[:-1])
except: self.stdscr.addstr(15, 4, 'Error.'); self.stdscr.refresh(); time.sleep(2)
if c == KEY_ESCAPE:
self.on_enter()
else: self.label_consumable = self.handle_text_input(c, self.label_consumable)
self.stdscr.erase()
elif c == KEY_ENTER and len(self.label_consumable) > 1:
self.stdscr.addstr(15, 4, 'Printing...')
self.stdscr.refresh()
try:
utils.print_consumable_label(self.label_consumable[:-1])
except:
self.stdscr.addstr(15, 4, 'Error.')
self.stdscr.refresh()
time.sleep(2)
self.on_enter()
self.stdscr.erase()
else:
self.label_consumable = self.handle_text_input(c, self.label_consumable)
elif self.sub_screen == 'forum_search':
if c == KEY_ESCAPE: self.on_enter()
if c == KEY_ESCAPE:
self.on_enter()
self.stdscr.erase()
elif c == KEY_ENTER and len(self.label_forum_search) > 2:
self.stdscr.addstr(16, 4, 'Searching...'); self.stdscr.refresh()
try: self.search_results = utils.search_forum_thread(self.label_forum_search[:-1])
except: self.stdscr.addstr(16, 4, 'Error.'); self.stdscr.refresh(); time.sleep(2)
self.stdscr.addstr(16, 4, 'Searching...')
self.stdscr.refresh()
try:
self.search_results = utils.search_forum_thread(self.label_forum_search[:-1])
except:
self.stdscr.addstr(16, 4, 'Error.')
self.stdscr.refresh()
time.sleep(2)
self.on_enter()
self.stdscr.erase()
return
self.sub_screen = 'forum_results'
else: self.label_forum_search = self.handle_text_input(c, self.label_forum_search)
self.stdscr.erase()
else:
self.label_forum_search = self.handle_text_input(c, self.label_forum_search)
elif self.sub_screen == 'forum_results':
if c == KEY_ESCAPE: self.on_enter()
if c == KEY_ESCAPE:
self.on_enter()
self.stdscr.erase()
elif c >= 49 and c <= 57:
num = int(chr(c))
if self.search_results and num <= len(self.search_results):
self.stdscr.addstr(21, 1, 'Printing...'); self.stdscr.refresh()
try: utils.print_forum_label(self.search_results[num-1])
except: self.stdscr.addstr(15, 4, 'Error.'); self.stdscr.refresh(); time.sleep(2)
self.stdscr.addstr(21, 1, 'Printing...')
self.stdscr.refresh()
try:
utils.print_forum_label(self.search_results[num-1])
except:
self.stdscr.addstr(15, 4, 'Error.')
self.stdscr.refresh()
time.sleep(2)
self.on_enter()
else: self.try_highlight(c)
else: self.try_highlight(c)
self.stdscr.erase()
else:
self.try_highlight(c)
else:
self.try_highlight(c)
def is_entry_key(self, c):
if self.sub_screen == 'menu':
button = self.get_button(c)
return button in ['t', 's', 'g', 'c', 'f']
return False
class GamesScreen(Screen):
@@ -692,17 +874,28 @@ class GamesScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
game_path = None
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif button == 's' and utils.HAS_SUDOKU: game_path = utils.SUDOKU_LOCATION + ' -c'
elif button == 'h' and utils.HAS_FROTZ and utils.HAS_HITCHHIKERS: game_path = utils.FROTZ_LOCATION + ' ' + utils.HITCHHIKERS_LOCATION
elif button == '2' and utils.HAS_2048: game_path = utils._2048_LOCATION
elif button == 'm' and utils.HAS_MORIA: game_path = utils.MORIA_LOCATION
elif button == 'n' and utils.HAS_NETHACK: game_path = utils.NETHACK_LOCATION
elif button == 'd' and utils.HAS_DRUGWARS: game_path = utils.DRUGWARS_LOCATION
else: self.try_highlight(c)
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 's' and utils.HAS_SUDOKU:
game_path = utils.SUDOKU_LOCATION + ' -c'
elif button == 'h' and utils.HAS_FROTZ and utils.HAS_HITCHHIKERS:
game_path = utils.FROTZ_LOCATION + ' ' + utils.HITCHHIKERS_LOCATION
elif button == '2' and utils.HAS_2048:
game_path = utils._2048_LOCATION
elif button == 'm' and utils.HAS_MORIA:
game_path = utils.MORIA_LOCATION
elif button == 'n' and utils.HAS_NETHACK:
game_path = utils.NETHACK_LOCATION
elif button == 'd' and utils.HAS_DRUGWARS:
game_path = utils.DRUGWARS_LOCATION
else:
self.try_highlight(c)
if game_path:
curses.nocbreak(); self.stdscr.keypad(False); curses.echo(); curses.endwin()
curses.nocbreak()
self.stdscr.keypad(False)
curses.echo()
curses.endwin()
logging.info('Spawning game: %s', game_path)
os.system(game_path)
exit()
@@ -740,33 +933,51 @@ I will be terse in my responses.''')]
self.stdscr.addstr(num + 5, 1, line)
if self.is_typing:
self.stdscr.addstr(21, 21, self.message_to_send)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Send [ESC] Cancel')
else:
self.stdscr.addstr(21, 21, '[E] Edit message', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
def handle_input(self, c):
button = self.get_button(c)
if self.is_typing:
if c == KEY_ESCAPE: self.is_typing = False; self.message_to_send = ''; self.stdscr.erase()
if c == KEY_ESCAPE:
self.is_typing = False
self.message_to_send = ''
self.stdscr.erase()
elif c == KEY_ENTER:
if len(self.message_to_send) > 1:
self.stdscr.addstr(21, 21, 'Sending...'); self.stdscr.clrtoeol(); self.stdscr.refresh()
self.stdscr.addstr(21, 21, 'Sending...')
self.stdscr.clrtoeol()
self.stdscr.refresh()
self.message_to_send = self.message_to_send[:-1]
lines = textwrap.wrap(self.message_to_send, width=80, initial_indent=' '*20, subsequent_indent=' '*20)
self.messages.append(''); self.messages.extend(lines)
self.messages.append('')
self.messages.extend(lines)
self.thread.append(dict(role='user', content=self.message_to_send))
gpt_reply = utils.message_protovac(self.thread)
self.thread.append(gpt_reply)
lines = textwrap.wrap(gpt_reply['content'], width=60)
self.messages.append(''); self.messages.extend(lines)
self.messages.append('')
self.messages.extend(lines)
self.stdscr.erase()
self.message_to_send = '_'
else: self.message_to_send = self.handle_text_input(c, self.message_to_send)
elif button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif button == 'e': self.is_typing = True; self.message_to_send = '_'
else: self.try_highlight(c)
else:
self.message_to_send = self.handle_text_input(c, self.message_to_send)
elif button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'e':
self.is_typing = True
self.message_to_send = '_'
else:
self.try_highlight(c)
def is_entry_key(self, c):
button = self.get_button(c)
return not self.is_typing and button == 'e'
class ThinkScreen(Screen):
@@ -787,29 +998,54 @@ class ThinkScreen(Screen):
self.stdscr.addstr(5, 1, 'Give Protovac something to think about.')
if self.is_typing:
self.stdscr.addstr(7, 4, self.think_to_send)
self.stdscr.clrtoeol()
for i in range(9, 19):
self.stdscr.move(i, 1)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[RETURN] Send [ESC] Cancel')
elif self.think_result:
self.stdscr.move(7, 4)
self.stdscr.clrtoeol()
for i in range(11, 19):
self.stdscr.move(i, 1)
self.stdscr.clrtoeol()
for _ in range(100):
try: self.stdscr.addstr(9, 4, self.think_result); break
except: self.think_result = self.think_result[:-5]
try:
self.stdscr.addstr(9, 4, self.think_result)
break
except:
self.think_result = self.think_result[:-5]
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if self.state.highlight_keys else 0)
else:
self.stdscr.addstr(7, 4, '[E] Edit prompt', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.clrtoeol()
self.stdscr.move(9, 1)
self.stdscr.clrtoeol()
self.stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if self.state.highlight_keys else 0)
self.stdscr.addstr(9, 1, 'Examples:')
self.stdscr.addstr(11, 4, '42 + 69'); self.stdscr.addstr(12, 4, '55 kg to lbs')
self.stdscr.addstr(13, 4, 'density of lead'); self.stdscr.addstr(14, 4, 'if x = 4, what is 3x + 50?')
self.stdscr.addstr(15, 4, 'force m=150g, a=50cm/s^2'); self.stdscr.addstr(16, 4, 'boiling point of benzene at 550 torr')
self.stdscr.addstr(17, 4, 'goats with highest milk yield'); self.stdscr.addstr(18, 4, 'how long did the Aztec empire last?')
self.stdscr.addstr(11, 4, '42 + 69')
self.stdscr.addstr(12, 4, '55 kg to lbs')
self.stdscr.addstr(13, 4, 'density of lead')
self.stdscr.addstr(14, 4, 'if x = 4, what is 3x + 50?')
self.stdscr.addstr(15, 4, 'force m=150g, a=50cm/s^2')
self.stdscr.addstr(16, 4, 'boiling point of benzene at 550 torr')
self.stdscr.addstr(17, 4, 'goats with highest milk yield')
self.stdscr.addstr(18, 4, 'how long did the Aztec empire last?')
self.stdscr.clrtoeol()
def handle_input(self, c):
button = self.get_button(c)
if self.is_typing:
if c == KEY_ESCAPE: self.is_typing = False; self.think_to_send = ''; self.stdscr.erase()
if c == KEY_ESCAPE:
self.is_typing = False
self.think_to_send = ''
self.stdscr.erase()
elif c == KEY_ENTER:
if len(self.think_to_send) > 1:
self.stdscr.addstr(9, 4, 'Thinking...'); self.stdscr.clrtoeol(); self.stdscr.refresh()
self.stdscr.addstr(9, 4, 'Thinking...')
self.stdscr.clrtoeol()
self.stdscr.refresh()
query = self.think_to_send[:-1]
logging.info('Thinking about: %s', query)
self.think_result = utils.think_send(query)
@@ -817,30 +1053,44 @@ class ThinkScreen(Screen):
self.is_typing = False
self.think_to_send = ''
self.stdscr.erase()
else: self.think_to_send = self.handle_text_input(c, self.think_to_send)
elif button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
elif button == 'e': self.is_typing = True; self.think_to_send = '_'
else: self.try_highlight(c)
else:
self.think_to_send = self.handle_text_input(c, self.think_to_send)
elif button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
elif button == 'e':
self.is_typing = True
self.think_to_send = '_'
else:
self.try_highlight(c)
def is_entry_key(self, c):
button = self.get_button(c)
return not self.is_typing and button == 'e'
class AboutScreen(Screen):
def draw(self):
self.stdscr.addstr(0, 1, 'PROTOVAC UNIVERSAL COMPUTER')
self.stdscr.addstr(2, 1, 'About'); self.stdscr.addstr(3, 1, '=====')
self.stdscr.addstr(2, 1, 'About')
self.stdscr.addstr(3, 1, '=====')
self.stdscr.addstr(5, 1, 'Protovac is a universal mainframe computer accessible by terminal.')
self.stdscr.addstr(7, 1, 'License'); self.stdscr.addstr(8, 1, '-------')
self.stdscr.addstr(7, 1, 'License')
self.stdscr.addstr(8, 1, '-------')
self.stdscr.addstr(10, 1, 'This program is free and open-source software licensed under the MIT License.')
self.stdscr.addstr(11, 1, 'Please see the LICENSE file for details. This means you have the right to')
self.stdscr.addstr(12, 1, 'study, change, and distribute the software and source code to anyone and for')
self.stdscr.addstr(13, 1, 'any purpose.')
self.stdscr.addstr(15, 1, 'Source code: github.com/Protospace/protovac')
self.stdscr.addstr(17, 1, 'Acknowledgements'); self.stdscr.addstr(18, 1, '----------------')
self.stdscr.addstr(17, 1, 'Acknowledgements')
self.stdscr.addstr(18, 1, '----------------')
self.stdscr.addstr(20, 1, 'Thanks to Peter for lending the Morrow MTD-60 terminal and Jamie for the Pi.')
self.stdscr.addstr(23, 1, '[B] Back', curses.A_REVERSE if self.state.highlight_keys else 0)
def handle_input(self, c):
button = self.get_button(c)
if button == 'b' or c == KEY_ESCAPE: self.state.current_screen = 'home'
else: self.try_highlight(c)
if button == 'b' or c == KEY_ESCAPE:
self.state.current_screen = 'home'
else:
self.try_highlight(c)
class HelpScreen(Screen):
def draw(self):
@@ -852,5 +1102,7 @@ class HelpScreen(Screen):
def handle_input(self, c):
button = self.get_button(c)
if button == 'o': self.state.current_screen = 'home'
else: self.try_highlight(c)
if button == 'o':
self.state.current_screen = 'home'
else:
self.try_highlight(c)