import os import time import psutil import tkinter as tk from tkinter import messagebox import random import subprocess # Constants SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) ASSETS_DIR = os.path.join(SCRIPT_DIR, 'assets') XP_FILE = os.path.join(ASSETS_DIR, 'xp.txt') LEVEL_FILE = os.path.join(ASSETS_DIR, 'level.txt') SESSION_LOG = os.path.join(ASSETS_DIR, 'session.log') QUESTIONS_FILE = os.path.join(ASSETS_DIR, 'questions.txt') TOTAL_TIME_FILE = os.path.join(ASSETS_DIR, 'total_time.txt') URL = "https://rol.redhat.com" TIMER_MINUTES = 20 # Utility Functions def initialize_assets(): """Ensure all necessary files and directories exist.""" os.makedirs(ASSETS_DIR, exist_ok=True) for file_path, default_content in [ (XP_FILE, '0'), (LEVEL_FILE, '1'), (SESSION_LOG, ''), (TOTAL_TIME_FILE, '0'), ]: if not os.path.exists(file_path): with open(file_path, 'w') as f: f.write(default_content) if not os.path.exists(QUESTIONS_FILE): raise FileNotFoundError(f"Questions file not found: {QUESTIONS_FILE}") def log_session(status): """Log session start or end with a timestamp.""" with open(SESSION_LOG, 'a') as f: f.write(f"Session {status}: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") def display_summary(): """Display a summary of total time, XP, and level.""" try: with open(TOTAL_TIME_FILE, 'r') as f: total_time = int(f.read().strip() or 0) # Handle empty file case except FileNotFoundError: total_time = 0 try: with open(XP_FILE, 'r') as f: xp = int(f.read().strip() or 0) except FileNotFoundError: xp = 0 try: with open(LEVEL_FILE, 'r') as f: level = int(f.read().strip() or 1) except FileNotFoundError: level = 1 hours, remainder = divmod(total_time, 3600) minutes, seconds = divmod(remainder, 60) print(f"Welcome to the RHEL Learning Script!") print(f"Total session time: {hours} hours, {minutes} minutes, and {seconds} seconds.") # Ensure correct output print(f"Current Level: {level}") print(f"Current XP: {xp}") print() return total_time, xp, level def kill_steam(): """Kill Steam only before the session starts.""" for proc in psutil.process_iter(['name']): if proc.info['name'] and "steam" in proc.info['name'].lower(): print("Stopping Steam...") proc.kill() def update_xp(correct): """Update XP and level based on whether the question was answered correctly.""" with open(XP_FILE, 'r') as f: xp = int(f.read().strip() or 0) with open(LEVEL_FILE, 'r') as f: level = int(f.read().strip() or 1) if correct: xp += 10 else: xp = max(0, xp - 5) # Ensure XP doesn't go below 0 if xp >= level * 100: level += 1 xp -= (level - 1) * 100 messagebox.showinfo("LEVEL UP!", f"LEVEL UP! You are now Level {level}!") with open(XP_FILE, 'w') as f: f.write(str(xp)) with open(LEVEL_FILE, 'w') as f: f.write(str(level)) with open(SESSION_LOG, 'a') as f: f.write(f"XP and level updated: {xp} XP, Level {level}\n") return xp, level def show_timer(minutes, questions_file, session_log, total_time, xp, level): def update_timer(): nonlocal seconds_left, elapsed_time if seconds_left > 0: seconds_left -= 1 elapsed_time += 1 hours, remainder = divmod(seconds_left, 3600) minutes, seconds = divmod(remainder, 60) timer_label.config(text=f"Time left: {hours:02}:{minutes:02}:{seconds:02}") root.after(1000, update_timer) else: end_session() def end_session(): with open(session_log, 'a') as f: f.write(f"Session duration: {elapsed_time // 60} minutes and {elapsed_time % 60} seconds\n") with open(TOTAL_TIME_FILE, 'w') as f: f.write(str(total_time + elapsed_time)) root.destroy() def on_closing(): end_session() def check_answer(): selected_answer = answer_var.get() if selected_answer == correct_answer: messagebox.showinfo("Correct!", "You selected the correct answer.") new_xp, new_level = update_xp(True) else: messagebox.showinfo("Incorrect", "You selected the wrong answer.") new_xp, new_level = update_xp(False) for button in radio_buttons: button.config(state=tk.DISABLED) xp_label.config(text=f"XP: {new_xp}") level_label.config(text=f"Level: {new_level}") def periodic_kill_steam(): kill_steam() root.after(10000, periodic_kill_steam) # Schedule to run every 10 seconds root = tk.Tk() root.title("RHEL Learning Timer") root.protocol("WM_DELETE_WINDOW", on_closing) seconds_left = minutes * 60 elapsed_time = 0 timer_label = tk.Label(root, text=f"Time left: {minutes:02}:00:00", font=("Helvetica", 16)) timer_label.pack(pady=20) xp_label = tk.Label(root, text=f"XP: {xp}", font=("Helvetica", 14)) xp_label.pack(pady=5) level_label = tk.Label(root, text=f"Level: {level}", font=("Helvetica", 14)) level_label.pack(pady=5) total_time_label = tk.Label(root, text=f"Total session time: {total_time // 3600} hours, {(total_time % 3600) // 60} minutes, and {total_time % 60} seconds", font=("Helvetica", 14)) total_time_label.pack(pady=5) with open(questions_file, 'r') as f: questions = f.readlines() random.shuffle(questions) # Shuffle the questions to ensure randomness question = random.choice(questions).strip() question_text, *answers, correct_answer = question.split('|') question_label = tk.Label(root, text=f"Question: {question_text}", font=("Helvetica", 14)) question_label.pack(pady=10) answer_var = tk.StringVar(value="") radio_buttons = [] for idx, answer in enumerate(answers, start=1): radio_button = tk.Radiobutton(root, text=answer, variable=answer_var, value=str(idx), font=("Helvetica", 12)) radio_button.pack(anchor='w') radio_buttons.append(radio_button) submit_button = tk.Button(root, text="Submit", command=check_answer, font=("Helvetica", 12)) submit_button.pack(pady=10) root.after(1000, update_timer) root.after(10000, periodic_kill_steam) # Start the periodic kill_steam function root.mainloop() def open_firefox(url): print(f"Attempting to open Firefox with URL: {url}") if 'DISPLAY' in os.environ: try: subprocess.Popen(['firefox', '--new-window', url], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) print("Firefox opened successfully.") except subprocess.CalledProcessError: print("Firefox is already running. Reusing the existing instance.") subprocess.Popen(['firefox', '--new-tab', url], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) else: print("No graphical environment detected. Skipping browser opening.") def main(): # Initialize assets initialize_assets() # Log session start log_session("start") # Display session summary total_time, xp, level = display_summary() # Stop Steam before session kill_steam() # Open Firefox with RHEL Learning open_firefox(URL) # Start session show_timer(TIMER_MINUTES, QUESTIONS_FILE, SESSION_LOG, total_time, xp, level) # Log session end log_session("end") if __name__ == "__main__": main()