|
| 1 | +""" |
| 2 | +Run the Python Study Buddy in a terminal |
| 3 | +This script creates a study buddy instance based on command line arguments. |
| 4 | +""" |
| 5 | + |
| 6 | +import sys |
| 7 | +import os |
| 8 | +from datetime import datetime |
| 9 | + |
| 10 | +def main(): |
| 11 | + """Run the study buddy using command line arguments.""" |
| 12 | + if len(sys.argv) < 3: |
| 13 | + print("Error: Missing required arguments.") |
| 14 | + print("Usage: python run_study_buddy.py <username> <level>") |
| 15 | + sys.exit(1) |
| 16 | + |
| 17 | + username = sys.argv[1] |
| 18 | + level = sys.argv[2] |
| 19 | + |
| 20 | + try: |
| 21 | + # Import the necessary modules |
| 22 | + from simple_study_buddy import PythonStudyBuddy, StudyProgress |
| 23 | + |
| 24 | + print(f"\n{'=' * 60}") |
| 25 | + print(f"🐍 Python Study Buddy - Terminal Session") |
| 26 | + print(f"{'=' * 60}") |
| 27 | + print(f"👤 Username: {username}") |
| 28 | + print(f"📊 Level: {level}") |
| 29 | + print(f"📅 Session Date: {datetime.now().strftime('%Y-%m-%d %H:%M')}") |
| 30 | + print(f"{'=' * 60}\n") |
| 31 | + |
| 32 | + # Load the exercise data based on the level |
| 33 | + exercise_data = load_exercises(level) |
| 34 | + |
| 35 | + if not exercise_data or level not in exercise_data or not exercise_data[level]: |
| 36 | + print(f"\n⚠️ Warning: No {level} exercises found. Falling back to default exercises.") |
| 37 | + |
| 38 | + # Create user progress |
| 39 | + user_progress = StudyProgress( |
| 40 | + user_name=username, |
| 41 | + level=level, |
| 42 | + completed_exercises=[], |
| 43 | + current_streak=0, |
| 44 | + total_exercises_attempted=0, |
| 45 | + start_date=datetime.now().isoformat(), |
| 46 | + achievements=[] |
| 47 | + ) |
| 48 | + |
| 49 | + # Create the study buddy instance |
| 50 | + study_buddy = PythonStudyBuddy( |
| 51 | + custom_exercises=exercise_data, |
| 52 | + custom_progress=user_progress |
| 53 | + ) |
| 54 | + |
| 55 | + # Print welcome message |
| 56 | + print(f"\n🚀 Starting Python Study Buddy session for {username} at {level} level!\n") |
| 57 | + |
| 58 | + # Run the study buddy |
| 59 | + study_buddy.run_study_session() |
| 60 | + |
| 61 | + print("\nSession completed. Thanks for studying Python!") |
| 62 | + |
| 63 | + except Exception as e: |
| 64 | + print(f"\n❌ Error: Failed to run study buddy: {str(e)}") |
| 65 | + sys.exit(1) |
| 66 | + |
| 67 | +def load_exercises(level): |
| 68 | + """Load exercises for the given level.""" |
| 69 | + import json |
| 70 | + import os |
| 71 | + from simple_study_buddy import Exercise |
| 72 | + |
| 73 | + exercises = {} |
| 74 | + exercise_files_found = False |
| 75 | + |
| 76 | + # First, look for specific level exercise file (e.g., beginner_exercises.json) |
| 77 | + try: |
| 78 | + level_file = f"{level}_exercises.json" |
| 79 | + if os.path.exists(level_file): |
| 80 | + print(f"📚 Loading exercises from {level_file}...") |
| 81 | + with open(level_file, 'r') as f: |
| 82 | + exercise_data = json.load(f) |
| 83 | + exercises[level] = [] |
| 84 | + |
| 85 | + for ex in exercise_data: |
| 86 | + exercises[level].append(Exercise( |
| 87 | + title=ex['title'], |
| 88 | + description=ex['description'], |
| 89 | + hint=ex['hint'], |
| 90 | + solution=ex['solution'], |
| 91 | + difficulty=ex['difficulty'] |
| 92 | + )) |
| 93 | + print(f"✅ Loaded {len(exercises[level])} exercises for {level} level!") |
| 94 | + exercise_files_found = True |
| 95 | + except Exception as e: |
| 96 | + print(f"❌ Could not load {level}_exercises.json: {e}") |
| 97 | + |
| 98 | + # If specific level file not found, look for any exercise files |
| 99 | + if not exercise_files_found: |
| 100 | + try: |
| 101 | + # Look for exercise files in the current directory |
| 102 | + exercise_files = [f for f in os.listdir() if f.endswith('_exercises.json')] |
| 103 | + |
| 104 | + if exercise_files: |
| 105 | + print(f"📚 Found {len(exercise_files)} exercise files.") |
| 106 | + |
| 107 | + for file in exercise_files: |
| 108 | + with open(file, 'r') as f: |
| 109 | + try: |
| 110 | + exercise_data = json.load(f) |
| 111 | + level_key = file.split('_')[0] # Get the level from filename |
| 112 | + if level_key not in exercises: |
| 113 | + exercises[level_key] = [] |
| 114 | + |
| 115 | + for ex in exercise_data: |
| 116 | + exercises[level_key].append(Exercise( |
| 117 | + title=ex['title'], |
| 118 | + description=ex['description'], |
| 119 | + hint=ex['hint'], |
| 120 | + solution=ex['solution'], |
| 121 | + difficulty=ex['difficulty'] |
| 122 | + )) |
| 123 | + print(f"✅ Loaded {len(exercises[level_key])} exercises for {level_key} level!") |
| 124 | + exercise_files_found = True |
| 125 | + except: |
| 126 | + print(f"❌ Could not parse {file}") |
| 127 | + except Exception as e: |
| 128 | + print(f"❌ Error loading exercises from files: {e}") |
| 129 | + |
| 130 | + # If no exercises found, provide fallback exercises |
| 131 | + if not exercise_files_found or level not in exercises or not exercises[level]: |
| 132 | + print("ℹ️ No appropriate exercises found. Creating default exercises...") |
| 133 | + return create_default_exercises() |
| 134 | + |
| 135 | + return exercises |
| 136 | + |
| 137 | +def create_default_exercises(): |
| 138 | + """Create default exercises as a fallback.""" |
| 139 | + from simple_study_buddy import Exercise |
| 140 | + |
| 141 | + return { |
| 142 | + "beginner": [ |
| 143 | + Exercise( |
| 144 | + title="Hello Variables", |
| 145 | + description="Create a variable called `name` and assign your name to it. Then print 'Hello, ' followed by your name.", |
| 146 | + hint="Use the print() function and string concatenation with '+' or f-strings to combine text.", |
| 147 | + solution='name = "Marlene"\nprint("Hello, " + name)\n# Or using f-strings:\n# print(f"Hello, {name}")', |
| 148 | + difficulty=1 |
| 149 | + ), |
| 150 | + Exercise( |
| 151 | + title="Basic Data Types", |
| 152 | + description="Create four variables: an integer called `age` with value 25, a float called `height` with value 1.75, a boolean called `is_student` with value True, and a string called `favorite_color` with a color of your choice. Print each variable on a separate line with a description.", |
| 153 | + hint="Make sure to use the correct data type for each variable. Use print() with descriptive text.", |
| 154 | + solution='age = 25\nheight = 1.75\nis_student = True\nfavorite_color = "blue"\n\nprint("Age:", age)\nprint("Height:", height)\nprint("Is student?", is_student)\nprint("Favorite color:", favorite_color)', |
| 155 | + difficulty=2 |
| 156 | + ), |
| 157 | + Exercise( |
| 158 | + title="Type Conversion", |
| 159 | + description='Create a variable `user_input` with the string value "42". Convert it to an integer, multiply it by 2, and print the result.', |
| 160 | + hint="Use the int() function to convert a string to an integer.", |
| 161 | + solution='user_input = "42"\nconverted_number = int(user_input)\nresult = converted_number * 2\nprint(result)', |
| 162 | + difficulty=2 |
| 163 | + ), |
| 164 | + Exercise( |
| 165 | + title="Basic Math Operations", |
| 166 | + description="Create two variables: `x` with value 10 and `y` with value 3. Calculate and print the following operations: addition, subtraction, multiplication, division, integer division, modulus, and exponentiation of these two variables.", |
| 167 | + hint="Python uses standard math operators: +, -, *, /, //, %, and ** for exponentiation.", |
| 168 | + solution="x = 10\ny = 3\n\nprint(\"Addition:\", x + y)\nprint(\"Subtraction:\", x - y)\nprint(\"Multiplication:\", x * y)\nprint(\"Division:\", x / y)\nprint(\"Integer Division:\", x // y)\nprint(\"Modulus:\", x % y)\nprint(\"Exponentiation:\", x ** y)", |
| 169 | + difficulty=3 |
| 170 | + ), |
| 171 | + Exercise( |
| 172 | + title="String Operations", |
| 173 | + description="Create a variable `first_name` with your first name and `last_name` with your last name. Combine them to create a `full_name` variable. Then print the full name, the length of your full name, and your full name in all uppercase letters.", |
| 174 | + hint="Use string concatenation to combine strings and the len() function to get string length. The upper() method converts a string to uppercase.", |
| 175 | + solution='first_name = "John"\nlast_name = "Doe"\nfull_name = first_name + " " + last_name\n\nprint("Full name:", full_name)\nprint("Length of full name:", len(full_name))\nprint("Uppercase full name:", full_name.upper())', |
| 176 | + difficulty=3 |
| 177 | + ) |
| 178 | + ], |
| 179 | + "intermediate": [ |
| 180 | + Exercise( |
| 181 | + title="List Comprehension", |
| 182 | + description="Create a list of squares for numbers 1-10 using list comprehension", |
| 183 | + hint="Use the syntax: [expression for item in range()]", |
| 184 | + solution="squares = [x**2 for x in range(1, 11)]\nprint(squares)", |
| 185 | + difficulty=3 |
| 186 | + ) |
| 187 | + ], |
| 188 | + "advanced": [ |
| 189 | + Exercise( |
| 190 | + title="Decorator Pattern", |
| 191 | + description="Create a decorator that times how long a function takes to run", |
| 192 | + hint="Use time.time() before and after the function call", |
| 193 | + solution="import time\nfrom functools import wraps\n\ndef timer(func):\n @wraps(func)\n def wrapper(*args, **kwargs):\n start = time.time()\n result = func(*args, **kwargs)\n end = time.time()\n print(f'{func.__name__} took {end-start:.4f} seconds')\n return result\n return wrapper", |
| 194 | + difficulty=5 |
| 195 | + ) |
| 196 | + ] |
| 197 | + } |
| 198 | + |
| 199 | +if __name__ == "__main__": |
| 200 | + main() |
0 commit comments