|
9 | 9 | from rich.prompt import Prompt |
10 | 10 | from rich.text import Text |
11 | 11 | import requests |
| 12 | +from rich.progress import Progress |
12 | 13 |
|
13 | 14 | # Initialize Console for Rich Formatting |
14 | 15 | console = Console() |
|
23 | 24 | In Harshit's SecureCoder Laboratory |
24 | 25 | """ |
25 | 26 |
|
| 27 | +USER = None |
| 28 | + |
26 | 29 | DB_FILE = "users.db" |
27 | | -USER = None # Stores the logged-in user |
28 | 30 |
|
29 | 31 | # Initialize Database |
30 | | -conn = sqlite3.connect(DB_FILE) |
| 32 | +conn = sqlite3.connect(DB_FILE, check_same_thread=False) # Allow safe multi-threaded access |
31 | 33 | cursor = conn.cursor() |
32 | | -cursor.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT, password TEXT, level INTEGER)") |
33 | | -cursor.execute("CREATE TABLE IF NOT EXISTS progress (user TEXT, date TEXT, score INTEGER)") |
| 34 | + |
| 35 | +# Enable Foreign Key Support for Database Integrity |
| 36 | +cursor.execute("PRAGMA foreign_keys = ON") |
| 37 | + |
| 38 | +# Create Users Table |
| 39 | +cursor.execute(""" |
| 40 | +CREATE TABLE IF NOT EXISTS users ( |
| 41 | + id INTEGER PRIMARY KEY AUTOINCREMENT, |
| 42 | + username TEXT UNIQUE NOT NULL, |
| 43 | + email TEXT UNIQUE NOT NULL, |
| 44 | + password TEXT NOT NULL, |
| 45 | + level INTEGER DEFAULT 1 |
| 46 | +) |
| 47 | +""") |
| 48 | + |
| 49 | +# Create Progress Table (Linked to Users) |
| 50 | +cursor.execute(""" |
| 51 | +CREATE TABLE IF NOT EXISTS progress ( |
| 52 | + id INTEGER PRIMARY KEY AUTOINCREMENT, |
| 53 | + user_id INTEGER NOT NULL, |
| 54 | + date TEXT NOT NULL, |
| 55 | + score INTEGER DEFAULT 0, |
| 56 | + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE |
| 57 | +) |
| 58 | +""") |
| 59 | + |
| 60 | +# Commit changes |
34 | 61 | conn.commit() |
35 | 62 |
|
| 63 | + |
36 | 64 | # Formspree URL for sending registration data |
37 | 65 | FORMSPREE_URL = "https://formspree.io/f/xyzkpywz" |
38 | 66 |
|
@@ -528,50 +556,89 @@ def sql_tips(): |
528 | 556 | time.sleep(2) |
529 | 557 | exit() |
530 | 558 |
|
| 559 | +import plotext as plt # Lightweight alternative to matplotlib |
531 | 560 |
|
532 | 561 | def user_dashboard(): |
533 | | - """Enhanced User Dashboard with progress bars and stylized menu""" |
| 562 | + """Enhanced User Dashboard with error handling and progress visualization""" |
534 | 563 | print_header() |
| 564 | + try: |
| 565 | + cursor.execute("SELECT id, level FROM users WHERE username=?", (USER,)) |
| 566 | + user_data = cursor.fetchone() # ✅ Correct indentation |
535 | 567 |
|
536 | | - cursor.execute("SELECT level FROM users WHERE username=?", (USER,)) |
537 | | - level = cursor.fetchone()[0] |
| 568 | + |
| 569 | + if not user_data: |
| 570 | + console.print("[red]Error: User not found! Returning to main menu...[/red]") |
| 571 | + time.sleep(2) |
| 572 | + main_menu() |
| 573 | + return |
| 574 | + |
| 575 | + user_id, level = user_data |
538 | 576 |
|
539 | | - cursor.execute("SELECT date, score FROM progress WHERE user=?", (USER,)) |
540 | | - progress_data = cursor.fetchall() |
541 | | - total_score = sum([row[1] for row in progress_data]) |
542 | | - avg_score = total_score / len(progress_data) if progress_data else 0 |
543 | | - progress_percentage = min(int(avg_score), 100) # User's average score as progress percentage |
| 577 | + # Fetch progress data |
| 578 | + cursor.execute("SELECT date, score FROM progress WHERE user_id=?", (user_id,)) |
| 579 | + progress_data = cursor.fetchall() |
| 580 | + |
| 581 | + if not progress_data: |
| 582 | + console.print("[yellow]No progress data available yet. Start a quiz to track progress![/yellow]") |
| 583 | + progress_data = [] # Ensure an empty list instead of None |
| 584 | + |
| 585 | + # Calculate total score & progress percentage |
| 586 | + total_score = sum(row[1] for row in progress_data) if progress_data else 0 |
| 587 | + avg_score = total_score / len(progress_data) if progress_data else 0 |
| 588 | + progress_percentage = min(int(avg_score), 100) # Normalize to 100% |
| 589 | + |
| 590 | + # Display User Information |
| 591 | + console.print(f"[bold green]Welcome back, {user_id}![/bold green]") |
| 592 | + console.print(f"[bold cyan]Current Level: {level}[/bold cyan]") |
| 593 | + console.print(f"[bold yellow]Your Progress: {progress_percentage}%[/bold yellow]\n") |
| 594 | + |
| 595 | + # Display Progress Bar |
| 596 | + with Progress() as progress: |
| 597 | + task = progress.add_task("[cyan]Your Progress...", total=100) |
| 598 | + progress.update(task, completed=progress_percentage) |
| 599 | + |
| 600 | + # Show Score History Graph using `plotext` |
| 601 | + if progress_data: |
| 602 | + dates = [row[0] for row in progress_data] |
| 603 | + scores = [row[1] for row in progress_data] |
| 604 | + |
| 605 | + plt.scatter(dates, scores, marker="dot", color="blue", label="Quiz Scores") |
| 606 | + plt.title(f"{user_id}'s Progress") |
| 607 | + plt.xlabel("Date") |
| 608 | + plt.ylabel("Score") |
| 609 | + plt.show() |
| 610 | + else: |
| 611 | + console.print("[yellow]No quiz history to display graph![/yellow]\n") |
| 612 | + |
| 613 | + # Leaderboard Section |
| 614 | + show_leaderboard() |
| 615 | + |
| 616 | + # Display Menu |
| 617 | + console.print("\n[bold yellow]Main Menu[/bold yellow]") |
| 618 | + console.print("[bold green][1] Practice Queries[/bold green] - Improve your SQL skills") |
| 619 | + console.print("[bold blue][2] Take a Quiz[/bold blue] - Test your SQL knowledge") |
| 620 | + console.print("[bold magenta][3] View My Profile[/bold magenta] - Track your progress") |
| 621 | + console.print("[bold cyan][4] Help[/bold cyan] - Get assistance and tips") |
| 622 | + console.print("[bold red][5] Logout[/bold red] - Exit and logout") |
| 623 | + |
| 624 | + choice = Prompt.ask("Please choose an option", choices=["1", "2", "3", "4", "5"]) |
| 625 | + |
| 626 | + if choice == "1": |
| 627 | + execute_sql() |
| 628 | + elif choice == "2": |
| 629 | + sql_quiz() |
| 630 | + elif choice == "3": |
| 631 | + view_profile() |
| 632 | + elif choice == "4": |
| 633 | + help_section() |
| 634 | + else: |
| 635 | + logout() |
| 636 | + |
| 637 | + except sqlite3.Error as e: |
| 638 | + console.print(f"[red]Database Error: {e}[/red]") |
| 639 | + time.sleep(2) |
| 640 | + main_menu() |
544 | 641 |
|
545 | | - console.print(f"[bold green]Welcome back, {USER}![/bold green]") |
546 | | - console.print(f"[bold cyan]Current Level: {level}[/bold cyan]") |
547 | | - console.print(f"[bold yellow]Your Progress: {progress_percentage}%[/bold yellow]") |
548 | | - |
549 | | - # Progress bar for visual feedback on learning progress |
550 | | - with Progress() as progress: |
551 | | - task = progress.add_task("[cyan]Your Progress...", total=100) |
552 | | - progress.update(task, completed=progress_percentage) |
553 | | - |
554 | | - # Display Menu with Stylized Options |
555 | | - console.print("\n[bold yellow]Main Menu[/bold yellow]") |
556 | | - console.print("[bold green][1] Practice Queries[/bold green] - Improve your SQL skills") |
557 | | - console.print("[bold blue][2] Take a Quiz[/bold blue] - Test your SQL knowledge") |
558 | | - console.print("[bold magenta][3] View My Profile[/bold magenta] - Track your progress") |
559 | | - console.print("[bold cyan][4] Help[/bold cyan] - Get assistance and tips") |
560 | | - console.print("[bold red][5] Logout[/bold red] - Exit and logout") |
561 | | - |
562 | | - choice = Prompt.ask("Please choose an option", choices=["1", "2", "3", "4", "5"]) |
563 | | - |
564 | | - # Navigate to the appropriate action based on the user's choice |
565 | | - if choice == "1": |
566 | | - execute_sql() |
567 | | - elif choice == "2": |
568 | | - sql_quiz() |
569 | | - elif choice == "3": |
570 | | - view_profile() |
571 | | - elif choice == "4": |
572 | | - help_section() |
573 | | - else: |
574 | | - logout() |
575 | 642 |
|
576 | 643 |
|
577 | 644 | def logout(): |
|
0 commit comments