import json import random import os import time import sqlite3 import sys import select import math DATA_FILE = "cosmic_data.json" TRIVIA_FILE = "trivia_facts.json" DB_FILE = "cosmic_timer.db" TRIVIA_WEIGHTS = { "300": 1, # 5 minutes "600": 2, # 10 minutes "1800": 5, # 30 minutes "3600": 10, # 1 hour } CARBON_PER_SECOND_KG = 0.0000005 # Estimated kg CO2 per second of runtime def init_db(): conn = sqlite3.connect(DB_FILE) c = conn.cursor() # Create or update users table to include carbon_footprint_kg and entropy_score c.execute(''' CREATE TABLE IF NOT EXISTS users ( username TEXT PRIMARY KEY, lifetime_seconds INTEGER DEFAULT 0, trivia_points INTEGER DEFAULT 0, carbon_footprint_kg REAL DEFAULT 0, entropy_score REAL DEFAULT 0 ) ''') # If running on existing DB missing the columns, add them c.execute("PRAGMA table_info(users)") columns = [col[1] for col in c.fetchall()] if "carbon_footprint_kg" not in columns: c.execute("ALTER TABLE users ADD COLUMN carbon_footprint_kg REAL DEFAULT 0") if "entropy_score" not in columns: c.execute("ALTER TABLE users ADD COLUMN entropy_score REAL DEFAULT 0") c.execute(''' CREATE TABLE IF NOT EXISTS sessions ( session_id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, end_time TIMESTAMP, duration_seconds INTEGER DEFAULT 0, FOREIGN KEY(username) REFERENCES users(username) ) ''') c.execute(''' CREATE TABLE IF NOT EXISTS trivia_events ( event_id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, session_id INTEGER, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, trivia_time_seconds INTEGER, points_awarded INTEGER, FOREIGN KEY(username) REFERENCES users(username), FOREIGN KEY(session_id) REFERENCES sessions(session_id) ) ''') c.execute(''' CREATE TABLE IF NOT EXISTS leaderboard_history ( record_id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, lifetime_rank INTEGER, trivia_rank INTEGER, FOREIGN KEY(username) REFERENCES users(username) ) ''') conn.commit() return conn def list_tables(): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("SELECT name FROM sqlite_master WHERE type='table'") tables = [row[0] for row in c.fetchall()] conn.close() print("\nšŸ“œ Tables in cosmic_timer.db:") for t in tables: print(f" - {t}") def ensure_user_exists(c, username): c.execute("SELECT 1 FROM users WHERE username = ?", (username,)) if not c.fetchone(): c.execute("INSERT INTO users (username) VALUES (?)", (username,)) def calculate_carbon_footprint(lifetime_seconds): return lifetime_seconds * CARBON_PER_SECOND_KG def calculate_entropy_score(trivia_events_count, total_seconds): # Prevent division by zero or log(0) if total_seconds == 0 or trivia_events_count == 0: return 0.0 p = trivia_events_count / total_seconds # Entropy per second using binary log (bits) entropy = -p * math.log2(p) - (1 - p) * math.log2(1 - p) if 0 < p < 1 else 0 # Scale by total_seconds to get total entropy "bits" accumulated return entropy * total_seconds def update_user_stats(c, username, session_seconds, trivia_points_this_session): # Count trivia events for this user from trivia_events table c.execute("SELECT COUNT(*) FROM trivia_events WHERE username = ?", (username,)) trivia_events_count = c.fetchone()[0] or 0 c.execute("SELECT lifetime_seconds, trivia_points FROM users WHERE username = ?", (username,)) row = c.fetchone() lifetime_seconds = (row[0] if row else 0) + session_seconds trivia_points = (row[1] if row else 0) + trivia_points_this_session carbon_footprint = calculate_carbon_footprint(lifetime_seconds) entropy_score = calculate_entropy_score(trivia_events_count, lifetime_seconds) c.execute(''' UPDATE users SET lifetime_seconds = ?, trivia_points = ?, carbon_footprint_kg = ?, entropy_score = ? WHERE username = ? ''', (lifetime_seconds, trivia_points, carbon_footprint, entropy_score, username)) return lifetime_seconds, trivia_points, carbon_footprint, entropy_score def update_session_end(c, session_id, session_seconds): c.execute(''' UPDATE sessions SET end_time = CURRENT_TIMESTAMP, duration_seconds = ? WHERE session_id = ? ''', (session_seconds, session_id)) def insert_trivia_event(c, username, session_id, trivia_time_seconds, points_awarded): c.execute(''' INSERT INTO trivia_events (username, session_id, trivia_time_seconds, points_awarded) VALUES (?, ?, ?, ?) ''', (username, session_id, trivia_time_seconds, points_awarded)) def insert_leaderboard_snapshot(c, username): c.execute("SELECT username FROM users ORDER BY lifetime_seconds DESC") lifetime_rank_list = [r[0] for r in c.fetchall()] lifetime_rank = lifetime_rank_list.index(username) + 1 if username in lifetime_rank_list else None c.execute("SELECT username FROM users ORDER BY trivia_points DESC") trivia_rank_list = [r[0] for r in c.fetchall()] trivia_rank = trivia_rank_list.index(username) + 1 if username in trivia_rank_list else None c.execute(''' INSERT INTO leaderboard_history (username, lifetime_rank, trivia_rank) VALUES (?, ?, ?) ''', (username, lifetime_rank, trivia_rank)) return lifetime_rank, trivia_rank def load_trivia_data(path, default={}): if os.path.exists(path): try: with open(path, 'r') as f: data = json.load(f) return {str(k): v for k, v in data.items()} except Exception as e: print(f"Warning: Failed to load {path} due to {e}, loading default.") else: print(f"Notice: {path} not found, initializing new data structure.") return default def format_time(seconds): hrs = seconds // 3600 mins = (seconds % 3600) // 60 secs = seconds % 60 return f"{hrs:02d}:{mins:02d}:{secs:02d}" def pick_random_fact(facts): return random.choice(facts) if facts else None def clear_terminal(): os.system('cls' if os.name == 'nt' else 'clear') def display_leaderboard(title, leaderboard, key, limit=10): print(f"\n {title}\n") if not leaderboard: print("(No users yet)") return print(f"{'Rank':>4} {'Username':<20} {title}") print("-" * 36) for i, entry in enumerate(leaderboard[:limit], start=1): name = entry['username'] value = entry[key] display_val = format_time(value) if key == 'lifetime_seconds' else str(value) print(f"{i:>4} {name:<20} {display_val}") def display_entropy_leaderboard(c, limit=10): c.execute("SELECT username, entropy_score FROM users ORDER BY entropy_score DESC LIMIT ?", (limit,)) entropy_lb = [{"username": r[0], "entropy_score": r[1]} for r in c.fetchall()] print("\n Top 10 Users by Entropy Score\n") if not entropy_lb: print("(No users yet)") return print(f"{'Rank':>4} {'Username':<20} Entropy Score (bits)") print("-" * 36) for i, entry in enumerate(entropy_lb, start=1): print(f"{i:>4} {entry['username']:<20} {entry['entropy_score']:.4f}") def non_blocking_input(timeout=0.0): """Non-blocking input on Unix and fallback on Windows.""" if os.name == 'nt': import msvcrt if msvcrt.kbhit(): return msvcrt.getwch() return None else: if select.select([sys.stdin], [], [], timeout)[0]: return sys.stdin.readline().strip() return None def run_timer(): username = input("Enter your username for leaderboard tracking: ").strip() or "Anonymous" conn = init_db() c = conn.cursor() trivia_data = load_trivia_data(TRIVIA_FILE, {}) ensure_user_exists(c, username) conn.commit() def session_loop(): c.execute("INSERT INTO sessions (username) VALUES (?)", (username,)) session_id = c.lastrowid conn.commit() session_seconds = 0 trivia_points_this_session = 0 shown_markers = set() shown_facts = [] print("Cosmic Timer started.") print("Type 'p' to pause, 'q' to quit, or 't' to list DB tables.\n") intervals = [300, 600, 1800, 3600] # base intervals to loop after 1 hour try: while True: time.sleep(1) session_seconds += 1 # Determine the trivia key based on current session_seconds if session_seconds <= 3600: key = str(session_seconds) else: # Loop intervals after the first hour elapsed_after_hour = session_seconds - 3600 cycle_time = elapsed_after_hour % 3600 # Find if cycle_time matches one of the intervals exactly if cycle_time in intervals: key = str(cycle_time) else: key = None if key and key in trivia_data and session_seconds not in shown_markers: fact = pick_random_fact(trivia_data[key]) if fact: shown_facts.append(f"ā± {format_time(session_seconds)} → {fact}") shown_markers.add(session_seconds) weight = TRIVIA_WEIGHTS.get(key, 1) trivia_points_this_session += weight insert_trivia_event(c, username, session_id, session_seconds, weight) conn.commit() clear_terminal() print(f" Cosmic Timer — User: {username}") print(f"Session Time: {format_time(session_seconds)}\n") print(" Trivia So Far:") for f in shown_facts: print(f) cmd = non_blocking_input() if cmd: cmd = cmd.lower() if cmd == 'p': input("\n=== PAUSED === Press Enter to continue...") elif cmd == 'q': raise KeyboardInterrupt elif cmd == 't': list_tables() input("\nPress Enter to continue...") except KeyboardInterrupt: return session_seconds, trivia_points_this_session, shown_facts, session_id while True: session_seconds, trivia_points_this_session, shown_facts, session_id = session_loop() lifetime_seconds, total_trivia_points, carbon_footprint, entropy_score = update_user_stats( c, username, session_seconds, trivia_points_this_session) update_session_end(c, session_id, session_seconds) lifetime_rank, trivia_rank = insert_leaderboard_snapshot(c, username) conn.commit() clear_terminal() print("\n\nExiting Cosmic Timer.") print(f"User: {username}") print(f"Session Runtime: {format_time(session_seconds)}") print(f"Lifetime Runtime: {format_time(lifetime_seconds)}") print(f"Estimated Carbon Footprint: {carbon_footprint:.6f} kg CO2") print(f"Trivia Points This Session: {trivia_points_this_session}") print(f"Total Trivia Points: {total_trivia_points}") print(f"Entropy Score: {entropy_score:.4f} bits") if shown_facts: print("\n Grand Cosmic Fact:") print(random.choice(shown_facts)) else: print("\n(No cosmic facts were obtained this run.)") c.execute("SELECT username, lifetime_seconds FROM users ORDER BY lifetime_seconds DESC LIMIT 10") lifetime_lb = [{"username": r[0], "lifetime_seconds": r[1]} for r in c.fetchall()] c.execute("SELECT username, trivia_points FROM users ORDER BY trivia_points DESC LIMIT 10") trivia_lb = [{"username": r[0], "trivia_points": r[1]} for r in c.fetchall()] display_leaderboard("Top 10 Users by Lifetime Time", lifetime_lb, "lifetime_seconds") display_leaderboard("Top 10 Users by Trivia Points", trivia_lb, "trivia_points") display_entropy_leaderboard(c) choice = input("\nStart a new session? (y/n): ").strip().lower() if choice != 'y': break conn.close() print("\n May you be as productive as the universe is efficent!") if __name__ == "__main__": run_timer()