diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f0017a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +lcd-env/ \ No newline at end of file diff --git a/random_timer.py b/random_timer.py index 7a0a926..72346fb 100755 --- a/random_timer.py +++ b/random_timer.py @@ -1,18 +1,27 @@ #!/usr/bin/env python3 """ -Catchphrase -Author: Jerick Oates +Catchphrase with LCD Output (Centered & Clean) """ import random import time import threading import sys +from RPLCD.i2c import CharLCD # ---------- CONFIG ---------- -WORDS_FILE = "words.txt" # file with one word per line -TIMER_SECONDS = 30 # how long the timer runs +WORDS_FILE = "words.txt" # file with one word per line +TIMER_SECONDS = 30 # how long the timer runs +I2C_ADDRESS = 0x27 # change if your LCD address is different +I2C_CHIP = 'PCF8574' # common backpack chip +# ---------- LCD ---------- +lcd = CharLCD(I2C_CHIP, I2C_ADDRESS) + +def lcd_print(text, line=0): + """Print text centered on given LCD line (0 or 1), padded to clear leftovers.""" + lcd.cursor_pos = (line, 0) + lcd.write_string(text.center(16)) # 16 chars wide # ---------- HELPERS ---------- def load_words(path=WORDS_FILE): @@ -27,59 +36,50 @@ def load_words(path=WORDS_FILE): print(f"āŒ Error loading words: {e}") sys.exit(1) - def pick_random(words): """Return a random word from the list.""" return random.choice(words) - # ---------- TIMER THREAD ---------- class CountdownTimer(threading.Thread): - """ - Background thread that counts down for TIMER_SECONDS. - When it finishes, it calls an optional callback. - """ def __init__(self, seconds=TIMER_SECONDS, on_finish=None): super().__init__() self.seconds = seconds - self.on_finish = on_finish # function to call when timer ends + self.on_finish = on_finish self._running = threading.Event() self._running.set() def run(self): for _ in range(self.seconds): if not self._running.is_set(): - break # stopped early by user + break time.sleep(1) - # Timer finished (or was stopped) self._running.clear() if self.on_finish: - self.on_finish() # announce completion + self.on_finish() def stop(self): - """Stop the timer before it reaches zero.""" self._running.clear() @property def is_running(self): return self._running.is_set() - # ---------- MAIN LOOP ---------- def main(): words = load_words() timer_thread = None - print("=== Catchphrase, but Better ===") + print("=== Catchphrase, but Better (LCD) ===") print("Commands:") print(" start - begin the 30-second timer and show a word immediately") print(" next - show another random word while the timer is running") print(" stop - cancel the timer early") print(" exit / quit - leave the program") - # Helper that prints when the timer ends def announce_finish(): print("\nā° Time is up! Returning to menu.") + lcd_print("Time is up!", line=0) print("=== Catchphrase ===") print("Commands:") print(" start - begin the 30-second timer and show a word immediately") @@ -90,13 +90,14 @@ def main(): while True: try: cmd = input("\n> ").strip().lower() - except EOFError: + except EOFError: break if cmd in ("exit", "quit"): if timer_thread and timer_thread.is_running: timer_thread.stop() timer_thread.join() + lcd_print("Goodbye!", line=0) print("šŸ‘‹ Goodbye!") break @@ -104,25 +105,28 @@ def main(): if timer_thread and timer_thread.is_running: print("[!] Timer is already running.") else: - # Start a new timer with the finish callback timer_thread = CountdownTimer(on_finish=announce_finish) - timer_thread.daemon = True # exit when main thread exits + timer_thread.daemon = True timer_thread.start() - # Show the first word right away - print(pick_random(words)) + word = pick_random(words) + print(word) + lcd_print(word, line=0) print(f"[+] 30-second timer started. ({TIMER_SECONDS}s)") elif cmd == "next": if not (timer_thread and timer_thread.is_running): print("[!] No active timer - use 'start' first.") else: - print(pick_random(words)) + word = pick_random(words) + print(word) + lcd_print(word, line=0) elif cmd == "stop": if timer_thread and timer_thread.is_running: timer_thread.stop() timer_thread.join() + lcd_print("Stopped early", line=0) print("[+] Timer stopped early.") else: print("[!] There is no running timer to stop.")