RandeBoo Post-Mortem: How 36% Became V1.0 (and the Triumph of the Aegean Theme)
Current Session Stats
Remember that 36% progress in Week 1? That pre-alpha bioweapon that balanced precariously between logic and runtime errors?
Well, the god of open-source worked a miracle. Or rather, to be precise, we did. Project 07 (RandeBoo) is now ready. We are in the phase of running final checks, writing documentation, and preparing mentally for the submission and the upcoming live presentation. Surprisingly, the database hasn't caught fire yet, and the professor hasn't sent us to the EAP mental health department.
But behind the upcoming delivery lies the classic story of every software project: design, panic, last-minute pivots, and an ungodly amount of caffeine.
🔄 The Great Pivot: From Silos to Full Stack
We started exactly as classic Software Engineering textbooks recommend: "You do Frontend, you do Backend, you do Testing."
The result? Deadlocks everywhere. The Frontend guy was waiting for the API, the Backend guy was waiting for the database schema, and the Tester was playing solitaire. Every single change required a Viber call with vacuum cleaner noises in the background just to get on the same page.
Realizing that at this rate we would graduate in 2035, I proposed a drastic pivot: Full Stack Module Ownership.
As I described in the Leap of Faith to Plato's Academy, this decision to drop our over-engineering hoods and become "mercenaries" (Full Stack) was what saved the project. We moved from the chaos of a modular architecture that looked like Phidias' sculptures (but didn't run) to raw reality.
Each team member took over a complete functional feature (module) and built it from top to bottom: from adapting and extending the database queries for their specific features to the Tkinter UI layout.
This reduced dependencies to zero. Collaboration with my other teammates became asynchronous and highly efficient. Everyone had their own sandbox to break things without bothering the others.
Of course, Git was anything but peaceful at first. We went through a whole drama: pushing to the wrong branches, fetches that refused to cooperate, and merge conflicts that caused existential crises. My main task (aside from coding) was running an informal crash course on how GitHub works and why we actually need it, trying to convince everyone that sharing code via email, Viber, or... 3.5" floppy disks belongs to the previous millennium. Eventually, the "training" paid off and Git stopped looking like a war zone.
🗄️ The 24-Hour Pointers-and-Queries Marathon (database.py)
Theory is nice in university halls. But when it's time to turn UML arrows into lines of code, reality slaps you in the face with sqlite3.db. One of my teammates did an outstanding job on the theoretical model (UML/ER). My task? To turn that ideal model into raw, functional SQLite code (database.py) and solve the application's biggest riddle: appointment conflict management.
If you think SQLite in Python is "simple," try writing an algorithm that checks if a new appointment overlaps with an existing one. Sounds easy? Now add to the equation: 1) the specific employee's working hours, 2) exceptions (e.g., the employee took a day off or it's a public holiday), 3) varying appointment durations, and 4) the fact that time is stored as text-based timestamps.
I spent Xe hours glued to the screen in a single weekend. The scenario was classic: 3 AM, the room smelling of Freddo Espresso, the computer fans screaming like a Caterpillar C18 Stage V turbine (literally), and me trying to figure out why my queries returned true for appointments that occurred in 2024. When the query finally ran correctly and the tests started showing green checkmarks, I felt like I had decoded the Antikythera Mechanism. Goodbye social life, welcome SQLite.
# The heart of the conflict check - SQLite Edition
cursor.execute('''
SELECT 1 FROM appointments
WHERE employee_id = ?
AND date = ?
AND (
(start_time <= ? AND end_time > ?) OR
(start_time < ? AND end_time >= ?) OR
(start_time >= ? AND end_time <= ?)
)
''', (emp_id, date_str, start_t, start_t, end_t, end_t, start_t, end_t))But the database wasn't static. My teammates added functions to serve their own modules and fine-tuned it to support export features and custom search queries, while we prayed to Saint Linus Torvalds that no other query would break during merge. Teamwork in practice (with a little divine/Linux intervention).
🎨 Aegean Theme: Making Tkinter Look Like the Cyclades
Let's be honest. Tkinter is the definition of "technological anachronism." Trying to build a modern, beautiful UI in Tkinter in 2026 is like trying to sculpt the Statue of David using only a rusty spoon. There's no CSS, no proper responsive layout (if you resize the window, widgets behave like they've been hit by an 8.0 magnitude earthquake), and color management feels like the era when monitors had 256 colors. If we had left the default gray buttons and fonts that look like an MS-DOS terminal, the professor would have developed depression before even seeing the functionality.
Thus, the Aegean Theme was born.
The UI finally had personality. It was no longer "just a Tkinter app." It was RandeBoo, featuring a clean layout, proper spacing, a modern flat design, and an aesthetic so premium that if Apple saw it, they would have hired us on the spot to design the next macOS (okay, let's not exaggerate, but for Tkinter standards, it was a minor aesthetic miracle).
🚦 SPA Routing: Single Page Architecture in Tkinter (aka The Hack of the Century)
When my classmate suggested, “Hey, why don't we just pop open 5-6 independent Toplevel windows to toggle between views? Who's going to notice?”, I felt a cold shiver run down my spine. Standard Tkinter, if left to its own devices, will turn your screen into a Windows Millennium adware pop-up nightmare in 5 seconds. No, folks. We are here to do software engineering, not sell CD-keys in Zappeion hangouts.
Since my DNA is basically React (I am a lover of the modern web), I decided to bring SPA (Single Page Application) routing to the Tkinter universe. Yes, SPA in Tkinter. No virtual DOM, no web browser, just raw Python and pure stubbornness.
I built a custom Router inside [gui_main.py] (the name of the file is, to say the least, funny). The logic is simple but effective: a dictionary mapping route strings to view-rendering functions, and a dynamic frame cleaner. Clicking a sidebar button executes a silent but merciless widget.destroy() on all children of the active frame, immediately drawing the new view on the same parent container. The view-switching is so snappy you'd think it's running on Next.js App Router at 120Hz.
def open_view(self, view_name: str) -> None:
# Έλεγχος αν η σελίδα που ζήτησε ο χρήστης υπάρχει στο routing map
if view_name not in self.views:
logging.warning(f"Unknown view name requested: {view_name}")
return
# Καθάρισμα της οθόνης από το προηγούμενο view για να μην γίνει μπάχαλο
self._clear_content()
# Δυναμική κλήση της function που σχεδιάζει το νέο panel
self.views[view_name]()
def _clear_content(self) -> None:
# Διαγραφή όλων των ενεργών widgets στο κεντρικό frame
# Με αυτόν τον τρόπο αποφεύγουμε τα memory leaks και το stackάρισμα των panels
for widget in self.content_frame.winfo_children():
widget.destroy()Clean, instantaneous view-switching with zero memory leaks, which would make even React developers weep with emotion (or despair over how we ended up writing an SPA in Tkinter).
💾 The Unsung Hero: backup.py (aka The Fallout Shelter for SQLite)
In the official university guidelines, the word “backup” was nowhere to be found. But if you've spent even a single week writing code for production-like environments, you know one absolute truth: users (and classmates) possess a unique superpower to obliterate databases in ways science cannot yet explain. A random Alt-F4 during a write transaction, or an experimental raw SQL query run on a whim, and poof—weeks of dummy data disappear. In our book, data loss is the ultimate sin.
So, I decided to dedicate $6$ whole hours (hours I could have spent sleeping or drinking yet another Freddo Espresso) to write a silent, autonomous guardian angel: backup.py.
The logic is simple but merciless. Every time gui_main.py boots, backup.py quietly wakes up in the background. It takes a precise snapshot of the active randeboo.db database, stamps it with the current date and time (e.g., randeboo_backup_20260531_2151.db), and stores it safely in a designated /backups directory.
Of course, to prevent the user's drive from choking on gigabytes of database snapshots after a few weeks of use, I implemented a custom file rotation algorithm: the system keeps only the 5 most recent backups, wiping out any older snapshots without hesitation.
The script was written with clean Pythonic patterns, featuring comprehensive comments in Greek (because when the database crashes, you need explanations in your native language):
import os
import shutil
import glob
from datetime import datetime
def perform_db_backup(db_path: str, backup_dir: str, max_backups: int = 5) -> None:
# Δημιουργία του φακέλου backups αν δεν υπάρχει ήδη
if not os.path.exists(backup_dir):
os.makedirs(backup_dir)
# Παραγωγή timestamp για το όνομα του αρχείου
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_filename = f"randeboo_backup_{timestamp}.db"
destination_path = os.path.join(backup_dir, backup_filename)
# Αντιγραφή της SQLite βάσης στο φάκελο backups
try:
shutil.copy2(db_path, destination_path)
except IOError as e:
print(f"Σφάλμα κατά τη δημιουργία του backup: {e}")
return
# Διαχείριση rotation: κρατάμε μόνο τα τελευταία max_backups αρχεία
backup_pattern = os.path.join(backup_dir, "randeboo_backup_*.db")
existing_backups = sorted(glob.glob(backup_pattern))
# Αν ξεπεράσαμε το όριο, σβήνουμε τα παλαιότερα
while len(existing_backups) > max_backups:
oldest_backup = existing_backups.pop(0)
try:
os.remove(oldest_backup)
except OSError as e:
print(f"Αδυναμία διαγραφής παλαιού backup {oldest_backup}: {e}")This single utility file was our shield. During manual testing, when a teammate decided to drop a table “just to see what happens,” backup.py restored the state and saved us from a near-fatal panic attack in exactly 3 seconds. Data loss avoided. Saint Linus approved.
⚡ The Final Crunch, Casper the Ghost, and "Creative" Copy-Paste
Like any self-respecting software release, the final days leading up to submission were a sprint for survival. And right on cue, the hard reality of university group projects knocked on our door.
We all know that in every academic group project, there is at least one teammate who is more invisible than Casper the Friendly Ghost. People who "undertake" critical modules, only to vanish into the shadows, leaving behind nothing but radio silence in the Viber chat groups. When I realized that the Employee module (gui_employees.py)—which had to be ready... yesterday—was still a completely blank page, I knew I had to step up for a solo coding rescue mission.
Instead of over-engineering or deep architectural debates, I resorted to the sacred, ancient art of DRY (or rather, Copy-Paste-Refactor). I took the tried-and-tested logic of the Customer module, swapped the labels, adjusted the SQLite queries, refactored the frames, and within $3$ hours (powered by a double Freddo Espresso), we had a fully functional Employee panel. It was the kind of work Casper would be proud of... if he ever read it.
The second major hurdle of the final stretch was email dispatch (email_service.py). Here, we faced a technical bottleneck: if you sent the email synchronously within the UI thread, the SMTP handshake with Google's servers froze the screen for $2$-$3$ seconds. In the user's mind, a frozen UI for $3$ seconds means "the app crashed, let's force close it."
The solution? Multi-threading. I implemented the email dispatch asynchronously, spinning up a separate thread for the SMTP request. During our live tests, the user clicked "Confirm Appointment," the UI remained instantly responsive, and the booking notification reached the inbox in less than $3$ seconds via a demo Gmail account using App Passwords. Pure magic.
🧠 The Big Takeaway: From Code Monkey to Architect (and a lesson in human dynamics)
This project was a lesson in maturity, not just on a technical level, but on a human one as well. It made me realize something crucial about my path: I am drawn to architectural thinking far more than just writing raw code. I care about how a system is structured, how modules communicate, and how to ensure scalability without turning the codebase into spaghetti. Coding is the tool; design is the art.
However, the most valuable lesson came from managing the team dynamic. I realized that for a project to succeed, it is not necessary for every single teammate to be a senior developer with years of experience. What truly matters is a strong willingness to learn and an open mind. A mind ready to listen, to understand what is happening and how, and most importantly, to challenge what they think they already know.
In software engineering (and in life), getting stuck in what we assume we know is the quickest path to failure. As the ancient Greeks famously put it—which aligns perfectly with our recent Leap of Faith—"I know one thing, that I know nothing." As you grow as a developer, you realize that the more you learn, the more you understand how little you actually know. And accepting that is the beginning of wisdom (and good debugging).
RandeBoo V1.0 is now ready. It was hard, it was exhausting, but the "shipping a product" feeling is highly addictive.
==================================================================== RANDEBOO SYSTEM COMPLIANCE REPORT - v1.0.0-RC1
[+] SQLite DB Connector :: OK (Antikythera Mechanism active) [+] SPA Router System :: OK (React developers weeping silently) [+] Aegean UI Palette :: OK (Apple notified unofficially) [+] Backup Daemon :: OK (Casper-proof rotation active) [+] SMTP Email Thread Handler :: OK (SMTP queue decoupled from UI) [+] Saint Linus Blessing :: ACTIVE (Queries holding strong)
[SYSTEM METRICS & TELEMETRY] [i] Freddo Espresso Injected :: 148.5 Liters (Core temp stable) [i] Casper Detection Rate :: 100% (Viber response: NaN) [i] Sanity Level :: [■□□□□□□□□□] 8.32% (CRITICAL_WARNING) [i] Floppy Disk Interceptor :: ACTIVE (3.5" floppy disks blocked)
[DEPLOYMENT ENGINE]
Status :: READY FOR SHIPMENT Verdict :: LEAP OF FAITH INITIATED ====================================================================