diff --git a/projects_registry.json b/projects_registry.json new file mode 100644 index 00000000..cee7e4df --- /dev/null +++ b/projects_registry.json @@ -0,0 +1,274 @@ +[ + { + "name": "Rock Paper Scissors", + "emoji": "๐ชจ", + "category": "games", + "difficulty": "beginner", + "description": "Battle against the computer in this classic hand game.", + "keywords": [ + "rock", + "paper", + "scissors", + "game", + "battle", + "computer" + ], + "path": "games/Rock-Paper-Scissor/Rock-Paper-Scissor.py" + }, + { + "name": "Dice Rolling", + "emoji": "๐ฒ", + "category": "games", + "difficulty": "beginner", + "description": "Roll two dice and calculate your fortune with emoji dice!", + "keywords": [ + "dice", + "roll", + "random", + "luck", + "board" + ], + "path": "games/Roling-Dice/Roling-Dice.py" + }, + { + "name": "Coin Flip", + "emoji": "๐ช", + "category": "games", + "difficulty": "beginner", + "description": "Predict heads or tails โ a quick decision maker.", + "keywords": [ + "coin", + "flip", + "heads", + "tails", + "random" + ], + "path": "games/Flipping-toss/Flipping-toss.py" + }, + { + "name": "Number Guessing Game", + "emoji": "๐ฏ", + "category": "games", + "difficulty": "beginner", + "description": "Guess the computer's secret number with smart hints.", + "keywords": [ + "guess", + "number", + "hints", + "game", + "interactive" + ], + "path": "games/Number-Guessing-Game/Number-Guessing-Game.py" + }, + { + "name": "Hangman Game", + "emoji": "๐ฎ", + "category": "games", + "difficulty": "intermediate", + "description": "Classic word-guessing game with 6 attempts.", + "keywords": [ + "hangman", + "word", + "guess", + "letters", + "classic" + ], + "path": "games/Hangman-Game/Hangman-Game.py" + }, + { + "name": "FLAMES Game", + "emoji": "๐", + "category": "games", + "difficulty": "beginner", + "description": "Discover your relationship status with two names!", + "keywords": [ + "flames", + "love", + "relationship", + "names", + "fun" + ], + "path": "games/FLAMES-Game/FLAMES-Game.py" + }, + { + "name": "Fibonacci Series", + "emoji": "โจ", + "category": "math", + "difficulty": "beginner", + "description": "Generate beautiful Fibonacci sequences visually.", + "keywords": [ + "fibonacci", + "series", + "sequence", + "math", + "pattern" + ], + "path": "math/Fibonacci-Series/Fibonacci-Series.py" + }, + { + "name": "Pascal's Triangle", + "emoji": "๐บ", + "category": "math", + "difficulty": "intermediate", + "description": "Explore mathematical beauty in Pascal's triangle.", + "keywords": [ + "pascal", + "triangle", + "pattern", + "math", + "rows" + ], + "path": "math/Pascal-Triangle/Pascal-Triangle.py" + }, + { + "name": "Armstrong Number Checker", + "emoji": "๐", + "category": "math", + "difficulty": "beginner", + "description": "Check if a number is an Armstrong number with breakdown.", + "keywords": [ + "armstrong", + "number", + "checker", + "narcissistic", + "math" + ], + "path": "math/Armstrong-Number/Armstrong-Number.py" + }, + { + "name": "Simple Calculator", + "emoji": "๐งฎ", + "category": "math", + "difficulty": "beginner", + "description": "All basic math operations plus power and modulus.", + "keywords": [ + "calculator", + "math", + "arithmetic", + "add", + "subtract" + ], + "path": "math/Simple-Calculator/Simple-Calculator.py" + }, + { + "name": "Prime Number Analyzer", + "emoji": "๐ฑ", + "category": "math", + "difficulty": "intermediate", + "description": "Check, generate, and factorize prime numbers.", + "keywords": [ + "prime", + "factor", + "analyze", + "sieve", + "number theory" + ], + "path": "math/Prime-Number-Analyzer/Prime-Number-Analyzer.py" + }, + { + "name": "Collatz Conjecture", + "emoji": "๐ข", + "category": "math", + "difficulty": "intermediate", + "description": "Explore the famous 3n+1 sequence until it reaches 1.", + "keywords": [ + "collatz", + "conjecture", + "sequence", + "3n+1", + "math" + ], + "path": "math/Collatz-Conjecture/Collatz-Conjecture.py" + }, + { + "name": "Projectile Motion Game", + "emoji": "๐", + "category": "math", + "difficulty": "advanced", + "description": "Launch projectiles and visualize trajectory stats with matplotlib.", + "keywords": [ + "projectile", + "physics", + "simulation", + "trajectory", + "matplotlib" + ], + "path": "math/Projectile-Motion-Game/Projectile-Motion-Game.py" + }, + { + "name": "Derivative Calculator", + "emoji": "โ", + "category": "math", + "difficulty": "advanced", + "description": "Compute first and nth polynomial derivatives at any point.", + "keywords": [ + "derivative", + "calculus", + "polynomial", + "math", + "algebra" + ], + "path": "math/Derivative-Calculator/Derivative-Calculator.py" + }, + { + "name": "Coordinate to Polar Transformation", + "emoji": "๐งญ", + "category": "math", + "difficulty": "intermediate", + "description": "Convert Cartesian (x,y) coordinates to polar form.", + "keywords": [ + "polar", + "cartesian", + "coordinate", + "geometry", + "angle" + ], + "path": "math/Coordinate-to-Polar-Transformation/Coordinate-to-Polar-Transformation.py" + }, + { + "name": "AP/GP/AGP/HP Recognizer", + "emoji": "๐", + "category": "math", + "difficulty": "intermediate", + "description": "Identify progression types from any number sequence.", + "keywords": [ + "progression", + "arithmetic", + "geometric", + "harmonic", + "sequence" + ], + "path": "math/AP-GP-AGP-HP-Recognizer/AP-GP-AGP-HP-Recognizer.py" + }, + { + "name": "Morse Code Translator", + "emoji": "๐ป", + "category": "utilities", + "difficulty": "beginner", + "description": "Translate text to Morse code and back โ bidirectional.", + "keywords": [ + "morse", + "code", + "translate", + "encrypt", + "dots", + "dashes" + ], + "path": "utilities/Text-to-Morse/Text-to-Morse.py" + }, + { + "name": "Tower of Hanoi", + "emoji": "๐ผ", + "category": "utilities", + "difficulty": "intermediate", + "description": "Solve the classic Tower of Hanoi puzzle step by step.", + "keywords": [ + "tower", + "hanoi", + "puzzle", + "recursion", + "algorithm" + ], + "path": "utilities/Tower-of-Hanoi/Tower-of-Hanoi.py" + } +] \ No newline at end of file diff --git a/search_projects.py b/search_projects.py index cf7884aa..f226f813 100644 --- a/search_projects.py +++ b/search_projects.py @@ -8,504 +8,19 @@ import os import subprocess import sys +import json # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ # Project Registry # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ -PROJECTS = [ - { - "name": "Rock Paper Scissors", - "emoji": "๐ชจ", - "category": "games", - "difficulty": "beginner", - "description": "Battle against the computer in this classic hand game.", - "keywords": ["rock", "paper", "scissors", "game", "battle", "computer"], - "path": "games/Rock-Paper-Scissor/Rock-Paper-Scissor.py", - }, - { - "name": "Dice Rolling", - "emoji": "๐ฒ", - "category": "games", - "difficulty": "beginner", - "description": "Roll two dice and calculate your fortune with emoji dice!", - "keywords": ["dice", "roll", "random", "luck", "board"], - "path": "games/Roling-Dice/Roling-Dice.py", - }, - { - "name": "Coin Flip", - "emoji": "๐ช", - "category": "games", - "difficulty": "beginner", - "description": "Predict heads or tails โ a quick decision maker.", - "keywords": ["coin", "flip", "heads", "tails", "random"], - "path": "games/Flipping-toss/Flipping-toss.py", - }, - { - "name": "Number Guessing Game", - "emoji": "๐ฏ", - "category": "games", - "difficulty": "beginner", - "description": "Guess the computer's secret number with smart hints.", - "keywords": ["guess", "number", "hints", "game", "interactive"], - "path": "games/Number-Guessing-Game/Number-Guessing-Game.py", - }, - { - "name": "Hangman Game", - "emoji": "๐ฎ", - "category": "games", - "difficulty": "intermediate", - "description": "Classic word-guessing game with 6 attempts.", - "keywords": ["hangman", "word", "guess", "letters", "classic"], - "path": "games/Hangman-Game/Hangman-Game.py", - }, - { - "name": "FLAMES Game", - "emoji": "๐", - "category": "games", - "difficulty": "beginner", - "description": "Discover your relationship status with two names!", - "keywords": ["flames", "love", "relationship", "names", "fun"], - "path": "games/FLAMES-Game/FLAMES-Game.py", - }, - { - "name": "Fibonacci Series", - "emoji": "โจ", - "category": "math", - "difficulty": "beginner", - "description": "Generate beautiful Fibonacci sequences visually.", - "keywords": ["fibonacci", "series", "sequence", "math", "pattern"], - "path": "math/Fibonacci-Series/Fibonacci-Series.py", - }, - { - "name": "Pascal's Triangle", - "emoji": "๐บ", - "category": "math", - "difficulty": "intermediate", - "description": "Explore mathematical beauty in Pascal's triangle.", - "keywords": ["pascal", "triangle", "pattern", "math", "rows"], - "path": "math/Pascal-Triangle/Pascal-Triangle.py", - }, - { - "name": "Armstrong Number Checker", - "emoji": "๐", - "category": "math", - "difficulty": "beginner", - "description": "Check if a number is an Armstrong number with breakdown.", - "keywords": ["armstrong", "number", "checker", "narcissistic", "math"], - "path": "math/Armstrong-Number/Armstrong-Number.py", - }, - { - "name": "Simple Calculator", - "emoji": "๐งฎ", - "category": "math", - "difficulty": "beginner", - "description": "All basic math operations plus power and modulus.", - "keywords": ["calculator", "math", "arithmetic", "add", "subtract"], - "path": "math/Simple-Calculator/Simple-Calculator.py", - }, - { - "name": "Prime Number Analyzer", - "emoji": "๐ฑ", - "category": "math", - "difficulty": "intermediate", - "description": "Check, generate, and factorize prime numbers.", - "keywords": ["prime", "factor", "analyze", "sieve", "number theory"], - "path": "math/Prime-Number-Analyzer/Prime-Number-Analyzer.py", - }, - { - "name": "Collatz Conjecture", - "emoji": "๐ข", - "category": "math", - "difficulty": "intermediate", - "description": "Explore the famous 3n+1 sequence until it reaches 1.", - "keywords": ["collatz", "conjecture", "sequence", "3n+1", "math"], - "path": "math/Collatz-Conjecture/Collatz-Conjecture.py", - }, - { - "name": "Projectile Motion Game", - "emoji": "๐", - "category": "math", - "difficulty": "advanced", - "description": "Launch projectiles and visualize trajectory stats with matplotlib.", - "keywords": ["projectile", "physics", "simulation", "trajectory", "matplotlib"], - "path": "math/Projectile-Motion-Game/Projectile-Motion-Game.py", - }, - { - "name": "Derivative Calculator", - "emoji": "โ", - "category": "math", - "difficulty": "advanced", - "description": "Compute first and nth polynomial derivatives at any point.", - "keywords": ["derivative", "calculus", "polynomial", "math", "algebra"], - "path": "math/Derivative-Calculator/Derivative-Calculator.py", - }, - { - "name": "Coordinate to Polar Transformation", - "emoji": "๐งญ", - "category": "math", - "difficulty": "intermediate", - "description": "Convert Cartesian (x,y) coordinates to polar form.", - "keywords": ["polar", "cartesian", "coordinate", "geometry", "angle"], - "path": "math/Coordinate-to-Polar-Transformation/Coordinate-to-Polar-Transformation.py", - }, - { - "name": "AP/GP/AGP/HP Recognizer", - "emoji": "๐", - "category": "math", - "difficulty": "intermediate", - "description": "Identify progression types from any number sequence.", - "keywords": ["progression", "arithmetic", "geometric", "harmonic", "sequence"], - "path": "math/AP-GP-AGP-HP-Recognizer/AP-GP-AGP-HP-Recognizer.py", - }, - { - "name": "Morse Code Translator", - "emoji": "๐ป", - "category": "utilities", - "difficulty": "beginner", - "description": "Translate text to Morse code and back โ bidirectional.", - "keywords": ["morse", "code", "translate", "encrypt", "dots", "dashes"], - "path": "utilities/Text-to-Morse/Text-to-Morse.py", - }, - { - "name": "Tower of Hanoi", - "emoji": "๐ผ", - "category": "utilities", - "difficulty": "intermediate", - "description": "Solve the classic Tower of Hanoi puzzle step by step.", - "keywords": ["tower", "hanoi", "puzzle", "recursion", "algorithm"], - "path": "utilities/Tower-of-Hanoi/Tower-of-Hanoi.py", - }, -] - -DIFFICULTY_ORDER = {"beginner": 1, "intermediate": 2, "advanced": 3} - -DIFFICULTY_BADGE = { - "beginner": "๐ข Beginner", - "intermediate": "๐ก Intermediate", - "advanced": "๐ด Advanced", -} - -CATEGORY_BADGE = { - "games": "๐ฎ Games", - "math": "๐ข Math", - "utilities": "๐ง Utilities", -} - - -def banner(): - print("\n" + "โ" * 56) - print(" ๐ Python Mini Projects โ Interactive Search") - print("โ" * 56) - - -def divider(): - print("โ" * 56) - - -def display_project(idx, p, show_path=False): - print(f"\n [{idx}] {p['emoji']} {p['name']}") - print(f" {CATEGORY_BADGE[p['category']]} {DIFFICULTY_BADGE[p['difficulty']]}") - print(f" {p['description']}") - if show_path: - print(f" ๐ {p['path']}") - - -def display_results(results, show_path=False): - if not results: - print("\n โ ๏ธ No projects found. Try a different search term.") - return - print(f"\n โ Found {len(results)} project(s):\n") - for idx, p in enumerate(results, start=1): - display_project(idx, p, show_path) - divider() - - -def search_by_keyword(query): - q = query.lower().strip() - return [ - p for p in PROJECTS - if q in p["name"].lower() - or q in p["description"].lower() - or any(q in kw for kw in p["keywords"]) - ] - - -def filter_by_category(category): - return [p for p in PROJECTS if p["category"] == category.lower().strip()] - - -def filter_by_difficulty(level): - return [p for p in PROJECTS if p["difficulty"] == level.lower().strip()] - - -def launch_project(projects): - if not projects: - return - divider() - choice = input(" โถ Enter project number to launch (or press Enter to skip): ").strip() - if not choice: - return - try: - idx = int(choice) - 1 - if 0 <= idx < len(projects): - path = projects[idx]["path"] - if os.path.exists(path): - print(f"\n ๐ Launching: {path}\n") - subprocess.run([sys.executable, path]) - else: - print(f"\n โ ๏ธ File not found: {path}") - print(" Make sure you're running this from the repo root.") - else: - print(" โ ๏ธ Invalid number.") - except ValueError: - print(" โ ๏ธ Please enter a valid number.") - - -def main(): - banner() - - while True: - print(""" - ๐ What would you like to do? - - 1 ๐ Search by keyword - 2 ๐ Browse by category (games / math / utilities) - 3 ๐ Filter by difficulty (beginner / intermediate / advanced) - 4 ๐ List all projects - 5 โ Exit -""") - choice = input(" Enter choice (1-5): ").strip() - - if choice == "1": - divider() - query = input(" ๐ Search Project: ").strip() - if query: - results = search_by_keyword(query) - display_results(results, show_path=True) - launch_project(results) - else: - print(" โ ๏ธ Please enter a search term.") - - elif choice == "2": - divider() - print(" Categories: games | math | utilities") - cat = input(" ๐ Enter category: ").strip() - if cat in ("games", "math", "utilities"): - results = filter_by_category(cat) - display_results(results, show_path=True) - launch_project(results) - else: - print(" โ ๏ธ Unknown category. Use: games, math, or utilities.") - - elif choice == "3": - divider() - print(" Levels: beginner | intermediate | advanced") - level = input(" ๐ Enter difficulty: ").strip() - if level in ("beginner", "intermediate", "advanced"): - results = filter_by_difficulty(level) - results = sorted(results, key=lambda p: p["name"]) - display_results(results, show_path=True) - launch_project(results) - else: - print(" โ ๏ธ Unknown level. Use: beginner, intermediate, or advanced.") - - elif choice == "4": - all_sorted = sorted( - PROJECTS, - key=lambda p: (p["category"], DIFFICULTY_ORDER[p["difficulty"]]) - ) - display_results(all_sorted, show_path=False) - launch_project(all_sorted) - - elif choice == "5": - print("\n ๐ Happy coding! See you next time.\n") - break - - else: - print(" โ ๏ธ Please enter a number from 1 to 5.") - - -if __name__ == "__main__": - main() -EOFcat > search_projects.py << 'EOF' -""" -๐ Interactive Search System for Python Mini Projects -===================================================== -Search, filter, and explore all projects by keyword, -category, or difficulty level. -""" - -import os -import subprocess -import sys - -# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ -# Project Registry -# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ -PROJECTS = [ - { - "name": "Rock Paper Scissors", - "emoji": "๐ชจ", - "category": "games", - "difficulty": "beginner", - "description": "Battle against the computer in this classic hand game.", - "keywords": ["rock", "paper", "scissors", "game", "battle", "computer"], - "path": "games/Rock-Paper-Scissor/Rock-Paper-Scissor.py", - }, - { - "name": "Dice Rolling", - "emoji": "๐ฒ", - "category": "games", - "difficulty": "beginner", - "description": "Roll two dice and calculate your fortune with emoji dice!", - "keywords": ["dice", "roll", "random", "luck", "board"], - "path": "games/Roling-Dice/Roling-Dice.py", - }, - { - "name": "Coin Flip", - "emoji": "๐ช", - "category": "games", - "difficulty": "beginner", - "description": "Predict heads or tails โ a quick decision maker.", - "keywords": ["coin", "flip", "heads", "tails", "random"], - "path": "games/Flipping-toss/Flipping-toss.py", - }, - { - "name": "Number Guessing Game", - "emoji": "๐ฏ", - "category": "games", - "difficulty": "beginner", - "description": "Guess the computer's secret number with smart hints.", - "keywords": ["guess", "number", "hints", "game", "interactive"], - "path": "games/Number-Guessing-Game/Number-Guessing-Game.py", - }, - { - "name": "Hangman Game", - "emoji": "๐ฎ", - "category": "games", - "difficulty": "intermediate", - "description": "Classic word-guessing game with 6 attempts.", - "keywords": ["hangman", "word", "guess", "letters", "classic"], - "path": "games/Hangman-Game/Hangman-Game.py", - }, - { - "name": "FLAMES Game", - "emoji": "๐", - "category": "games", - "difficulty": "beginner", - "description": "Discover your relationship status with two names!", - "keywords": ["flames", "love", "relationship", "names", "fun"], - "path": "games/FLAMES-Game/FLAMES-Game.py", - }, - { - "name": "Fibonacci Series", - "emoji": "โจ", - "category": "math", - "difficulty": "beginner", - "description": "Generate beautiful Fibonacci sequences visually.", - "keywords": ["fibonacci", "series", "sequence", "math", "pattern"], - "path": "math/Fibonacci-Series/Fibonacci-Series.py", - }, - { - "name": "Pascal's Triangle", - "emoji": "๐บ", - "category": "math", - "difficulty": "intermediate", - "description": "Explore mathematical beauty in Pascal's triangle.", - "keywords": ["pascal", "triangle", "pattern", "math", "rows"], - "path": "math/Pascal-Triangle/Pascal-Triangle.py", - }, - { - "name": "Armstrong Number Checker", - "emoji": "๐", - "category": "math", - "difficulty": "beginner", - "description": "Check if a number is an Armstrong number with breakdown.", - "keywords": ["armstrong", "number", "checker", "narcissistic", "math"], - "path": "math/Armstrong-Number/Armstrong-Number.py", - }, - { - "name": "Simple Calculator", - "emoji": "๐งฎ", - "category": "math", - "difficulty": "beginner", - "description": "All basic math operations plus power and modulus.", - "keywords": ["calculator", "math", "arithmetic", "add", "subtract"], - "path": "math/Simple-Calculator/Simple-Calculator.py", - }, - { - "name": "Prime Number Analyzer", - "emoji": "๐ฑ", - "category": "math", - "difficulty": "intermediate", - "description": "Check, generate, and factorize prime numbers.", - "keywords": ["prime", "factor", "analyze", "sieve", "number theory"], - "path": "math/Prime-Number-Analyzer/Prime-Number-Analyzer.py", - }, - { - "name": "Collatz Conjecture", - "emoji": "๐ข", - "category": "math", - "difficulty": "intermediate", - "description": "Explore the famous 3n+1 sequence until it reaches 1.", - "keywords": ["collatz", "conjecture", "sequence", "3n+1", "math"], - "path": "math/Collatz-Conjecture/Collatz-Conjecture.py", - }, - { - "name": "Projectile Motion Game", - "emoji": "๐", - "category": "math", - "difficulty": "advanced", - "description": "Launch projectiles and visualize trajectory stats with matplotlib.", - "keywords": ["projectile", "physics", "simulation", "trajectory", "matplotlib"], - "path": "math/Projectile-Motion-Game/Projectile-Motion-Game.py", - }, - { - "name": "Derivative Calculator", - "emoji": "โ", - "category": "math", - "difficulty": "advanced", - "description": "Compute first and nth polynomial derivatives at any point.", - "keywords": ["derivative", "calculus", "polynomial", "math", "algebra"], - "path": "math/Derivative-Calculator/Derivative-Calculator.py", - }, - { - "name": "Coordinate to Polar Transformation", - "emoji": "๐งญ", - "category": "math", - "difficulty": "intermediate", - "description": "Convert Cartesian (x,y) coordinates to polar form.", - "keywords": ["polar", "cartesian", "coordinate", "geometry", "angle"], - "path": "math/Coordinate-to-Polar-Transformation/Coordinate-to-Polar-Transformation.py", - }, - { - "name": "AP/GP/AGP/HP Recognizer", - "emoji": "๐", - "category": "math", - "difficulty": "intermediate", - "description": "Identify progression types from any number sequence.", - "keywords": ["progression", "arithmetic", "geometric", "harmonic", "sequence"], - "path": "math/AP-GP-AGP-HP-Recognizer/AP-GP-AGP-HP-Recognizer.py", - }, - { - "name": "Morse Code Translator", - "emoji": "๐ป", - "category": "utilities", - "difficulty": "beginner", - "description": "Translate text to Morse code and back โ bidirectional.", - "keywords": ["morse", "code", "translate", "encrypt", "dots", "dashes"], - "path": "utilities/Text-to-Morse/Text-to-Morse.py", - }, - { - "name": "Tower of Hanoi", - "emoji": "๐ผ", - "category": "utilities", - "difficulty": "intermediate", - "description": "Solve the classic Tower of Hanoi puzzle step by step.", - "keywords": ["tower", "hanoi", "puzzle", "recursion", "algorithm"], - "path": "utilities/Tower-of-Hanoi/Tower-of-Hanoi.py", - }, -] +REGISTRY_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "projects_registry.json") + +try: + with open(REGISTRY_PATH, "r", encoding="utf-8") as f: + PROJECTS = json.load(f) +except Exception as e: + print(f"Error loading project registry: {e}") + PROJECTS = [] DIFFICULTY_ORDER = {"beginner": 1, "intermediate": 2, "advanced": 3} diff --git a/utilities/Progress-Tracker/Progress-Tracker.py b/utilities/Progress-Tracker/Progress-Tracker.py index 787fccda..38ce83ae 100644 --- a/utilities/Progress-Tracker/Progress-Tracker.py +++ b/utilities/Progress-Tracker/Progress-Tracker.py @@ -10,33 +10,34 @@ # โโ Config โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ DATA_FILE = "completed_projects.json" +# Load Project Registry from projects_registry.json +REGISTRY_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "projects_registry.json")) + ALL_PROJECTS = { - "๐ฒ Games": [ - "Rock-Paper-Scissor", - "Dice-Rolling", - "Coin-Flip", - "Number-Guessing-Game", - "Hangman-Game", - "FLAMES-Game", - ], - "๐ข Math": [ - "Fibonacci-Series", - "Pascals-Triangle", - "Armstrong-Number", - "Simple-Calculator", - "Collatz-Conjecture", - "Prime-Number-Analyzer", - "Projectile-Motion-Game", - "Coordinate-to-Polar-Transformation", - "Derivative-Calculator", - "AP-GP-AGP-HP-Recognizer", - ], - "๐ Utilities": [ - "Text-to-Morse", - "Tower-of-Hanoi", - ], + "๐ฒ Games": [], + "๐ข Math": [], + "๐ Utilities": [] +} + +CATEGORY_MAP = { + "games": "๐ฒ Games", + "math": "๐ข Math", + "utilities": "๐ Utilities" } +try: + with open(REGISTRY_PATH, "r", encoding="utf-8") as f: + registry = json.load(f) + for p in registry: + cat_key = CATEGORY_MAP.get(p["category"]) + if cat_key: + parts = p["path"].split("/") + if len(parts) >= 2: + proj_name = parts[-2] + ALL_PROJECTS[cat_key].append(proj_name) +except Exception as e: + print(f"Error loading project registry: {e}") + # Flatten for quick lookup ALL_PROJECT_NAMES = [p for projects in ALL_PROJECTS.values() for p in projects] TOTAL = len(ALL_PROJECT_NAMES) @@ -48,7 +49,26 @@ def load_data() -> dict: """Load saved progress from JSON file, or return a fresh state.""" if os.path.exists(DATA_FILE): with open(DATA_FILE, "r") as f: - return json.load(f) + data = json.load(f) + # Migrate old names to new folder names + migrations = { + "Dice-Rolling": "Roling-Dice", + "Coin-Flip": "Flipping-toss", + "Pascals-Triangle": "Pascal-Triangle" + } + completed = data.get("completed", {}) + updated_completed = {} + mutated = False + for k, v in completed.items(): + if k in migrations: + updated_completed[migrations[k]] = v + mutated = True + else: + updated_completed[k] = v + if mutated: + data["completed"] = updated_completed + save_data(data) + return data return {"completed": {}} # {project_name: "YYYY-MM-DD HH:MM"} diff --git a/web-app/js/projects/progress-tracker.js b/web-app/js/projects/progress-tracker.js index b3c7c1d9..22464d60 100644 --- a/web-app/js/projects/progress-tracker.js +++ b/web-app/js/projects/progress-tracker.js @@ -52,65 +52,151 @@ function getProgressTrackerHTML() { } function initProgressTracker() { - const PROJECTS = { - '๐ฒ Games': ['Rock-Paper-Scissor','Dice-Rolling','Coin-Flip','Number-Guessing-Game','Hangman-Game','FLAMES-Game'], - '๐ข Math': ['Fibonacci-Series','Pascals-Triangle','Armstrong-Number','Simple-Calculator','Collatz-Conjecture','Prime-Number-Analyzer','Projectile-Motion-Game','Coordinate-to-Polar','Derivative-Calculator','AP-GP-AGP-HP-Recognizer'], - '๐ Utilities': ['Text-to-Morse','Tower-of-Hanoi'] - }; - const TOTAL = Object.values(PROJECTS).flat().length; const KEY = 'pt_completed_v1'; + const migrations = { + "Dice-Rolling": "Roling-Dice", + "Coin-Flip": "Flipping-toss", + "Pascals-Triangle": "Pascal-Triangle" + }; - const load = () => { try { return JSON.parse(localStorage.getItem(KEY)) || []; } catch { return []; } }; + const load = () => { + try { + let list = JSON.parse(localStorage.getItem(KEY)) || []; + let mutated = false; + list = list.map(item => { + if (migrations[item]) { + mutated = true; + return migrations[item]; + } + return item; + }); + if (mutated) { + localStorage.setItem(KEY, JSON.stringify(list)); + } + return list; + } catch { + return []; + } + }; const save = (l) => localStorage.setItem(KEY, JSON.stringify(l)); - function render() { - const done = load(); - const count = done.length; - const pct = Math.round((count / TOTAL) * 100); - document.getElementById('pt-bar-fill').style.width = pct + '%'; - document.getElementById('pt-bar-label').textContent = count + ' / ' + TOTAL + ' completed'; - document.getElementById('pt-s-done').textContent = count; - document.getElementById('pt-s-left').textContent = TOTAL - count; - document.getElementById('pt-s-pct').textContent = pct + '%'; - const container = document.getElementById('pt-cats'); - if (!container) return; - container.textContent = ''; - for (const [cat, projects] of Object.entries(PROJECTS)) { - const catDone = projects.filter(p => done.includes(p)).length; - const sec = document.createElement('div'); - sec.textContent = '