What awaits you?
In this project you build PyBuddy CLI โ an interactive command-line assistant, that combines all concepts from the 13 chapters. In the end you have a complete program, that you can proudly showcase in your portfolio.
Project Overview
PyBuddy CLI is a personal assistant in the terminal. It greets the user, saves a profile, runs small tools and remembers everything in a JSON file. This project uses all chapter concepts:
input() and f-strings for the greetingwhile loop for the main menudatetime, json, random)Requirements
Your PyBuddy CLI must have the following features. Work through the points step by step:
-
Greeting: Asks for the name and greets the user personally.
-
Profile System: Saves name, level, XP and badges in a dictionary.
-
Main Menu: Shows a menu with options and repeats until "exit".
-
XP Calculator: Calculates total XP from base XP, multiplier and bonus.
-
To-Do List: Add, display and complete tasks.
-
Random Quote: Shows a random motivational quote from a list.
-
Save & Load: Save profile as JSON and reload on startup.
Step by Step
Step 1: Project Structure
Create a folder pybuddy-cli/ with two files:
pybuddy-cli/
โโโ main.py # Main program
โโโ profile.json # Created automatically
Step 2: The Basic Structure
Start with imports and profile management:
import json
import random
from datetime import datetime
PROFILE_FILE = "profile.json"
QUOTES = [
"Every expert was once a beginner.",
"Code is like humor โ if you have to explain it, it is bad.",
"The best way to learn Python: Typing, not just reading!",
"Errors are not mistakes โ they are debugging opportunities.",
"A program that runs is better than a perfect one that does not exist."
]
def load_profile():
"""Loads the profile from the JSON file or creates a new one."""
try:
with open(PROFILE_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return {
"name": "",
"level": 1,
"xp": 0,
"badges": ["PyBuddy User"],
"tasks": []
}
def save_profile(profile):
"""Saves the profile as JSON."""
with open(PROFILE_FILE, "w", encoding="utf-8") as f:
json.dump(profil, f, indent=2, ensure_ascii=False)
Step 3: The Tool Functions
Each menu feature is implemented as its own function:
def show_status(profile):
"""Displays the current profile."""
print(f"\n{'='*30}")
print(f" ๐ค {profil['name']}")
print(f" ๐ Level {profil['level']}")
print(f" โญ {profil['xp']} XP")
print(f" ๐๏ธ Badges: {', '.join(profil['badges'])}")
print(f"{'='*30}\n")
def xp_calculator(profile):
"""Calculates new XP and checks for level-up."""
basis = int(input("Base XP: "))
mult = float(input("Multiplier (e.g. 1.5): "))
bonus = int(input("Bonus-XP: "))
new_xp = int(basis * mult + bonus)
profil["xp"] += new_xp
# Level-Up alle 500 XP
new_level = profil["xp"] // 500 + 1
if new_level > profil["level"]:
profil["level"] = new_level
badge = f"Level {new_level}"
if badge not in profil["badges"]:
profil["badges"].append(badge)
print(f"๐ Level-Up! You are now level {new_level}!")
print(f"โ +{new_xp} XP received!")
print(f"โญ Total: {profil['xp']} XP")
def todo_manager(profil):
"""Manages the to-do list."""
print("\n๐ To-Do Manager")
print("[1] Add task")
print("[2] Show tasks")
print("[3] Complete task")
wahl = input("Choice: ")
if wahl == "1":
task = input("New task: ")
profil["tasks"].append({"text": task, "done": False})
print("โ
Added!")
elif wahl == "2":
if not profil["tasks"]:
print("โน๏ธ No tasks available.")
for i, task in enumerate(profil["tasks"], 1):
status = "โ" if task["done"] else "โก"
print(f" {i}. {status} {task['text']}")
elif wahl == "3":
nr = int(input("Number of completed task: "))
if 1 <= nr <= len(profil["tasks"]):
profil["tasks"][nr-1]["done"] = True
profil["xp"] += 10
print("โ
Done! +10 XP")
def zufalls_zitat():
"""Shows a random quote."""
print(f"\n๐ฌ {random.choice(QUOTES)}\n")
def uhrzeit_anzeigen():
"""Shows the current time."""
now = datetime.now()
print(f"๐ {now.strftime('%H:%M:%S')} โ {now.strftime('%d.%m.%Y')}")
Step 4: The Main Menu
The heart: A while loop that shows the menu and processes the input:
def main_menu(profile):
"""Shows the main menu and processes input."""
while True:
print(f"\n{'='*30}")
print(f" ๐ค PyBuddy CLI")
print(f" Hello, {profile['name']}!")
print(f"{'='*30}")
print(" [1] ๐ค Show profile")
print(" [2] โ Calculate XP")
print(" [3] ๐ To-Do Manager")
print(" [4] ๐ฌ Random Quote")
print(" [5] ๐ Time")
print(" [0] ๐ช Exit")
print(f"{'='*30}")
wahl = input("\nChoose (0-5): ").strip()
if wahl == "0":
save_profile(profile)
print(f"๐พ Profile saved. Goodbye, {profil['name']}!")
break
elif wahl == "1":
show_status(profile)
elif wahl == "2":
xp_calculator(profile)
elif wahl == "3":
todo_manager(profil)
elif wahl == "4":
zufalls_zitat()
elif wahl == "5":
uhrzeit_anzeigen()
else:
print("โ ๏ธ Invalid input. Please enter 0-5.")
Step 5: The Entry Point
Connect everything in the main() function:
def main():
print("๐ค Welcome to PyBuddy CLI!")
profil = load_profile()
# Erster Start?
if not profil["name"]:
profil["name"] = input("What is your name? ").strip()
print(f"\n๐ Hello {profil['name']}! Nice to have you here.")
save_profile(profile)
else:
print(f"\n๐ Welcome back, {profil['name']}!")
main_menu(profile)
if __name__ == "__main__":
main()
The Complete Program
Here is the complete code in one file. Copy it to main.py and run it with python main.py:
"""
PyBuddy CLI โ Abschlussprojekt Python Classic
All 13 chapters united in one interactive assistant.
"""
import json
import random
from datetime import datetime
PROFILE_FILE = "profile.json"
QUOTES = [
"Every expert was once a beginner.",
"Code is like humor โ if you have to explain it, it is bad.",
"The best way to learn Python: Typing, not just reading!",
"Errors are not mistakes โ they are debugging opportunities.",
"A program that runs is better than a perfect one that does not exist."
]
# โโ Profile Management โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def load_profile():
try:
with open(PROFILE_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return {
"name": "", "level": 1, "xp": 0,
"badges": ["PyBuddy User"], "tasks": []
}
def save_profile(profile):
with open(PROFILE_FILE, "w", encoding="utf-8") as f:
json.dump(profil, f, indent=2, ensure_ascii=False)
# โโ Tool-Funktionen โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def show_status(profile):
print(f"\n{'='*35}")
print(f" Profile: {profile['name']}")
print(f" Level {profil['level']} | {profil['xp']} XP")
print(f" Badges: {', '.join(profil['badges'])}")
print(f" Tasks: {len(profil['tasks'])}")
print(f"{'='*35}\n")
def xp_calculator(profile):
basis = int(input("Base XP: "))
mult = float(input("Multiplier: "))
bonus = int(input("Bonus: "))
new_xp = int(basis * mult + bonus)
profil["xp"] += new_xp
new_level = profil["xp"] // 500 + 1
if new_level > profil["level"]:
profil["level"] = new_level
profil["badges"].append(f"Level {new_level}")
print(f">>> Level-Up! Level {new_level}!")
print(f">>> +{new_xp} XP | Total: {profil['xp']}")
def todo_manager(profil):
print("\n--- To-Do Manager ---")
print("[1] Add [2] Show [3] Done")
wahl = input("Choice: ")
if wahl == "1":
profil["tasks"].append({"text": input("Task: "), "done": False})
print("Added!")
elif wahl == "2":
for i, t in enumerate(profil["tasks"], 1):
s = "[x]" if t["done"] else "[ ]"
print(f" {i}. {s} {t['text']}")
elif wahl == "3":
nr = int(input("Nummer: "))
profil["tasks"][nr-1]["done"] = True
profil["xp"] += 10
print("Done! +10 XP")
def zufalls_zitat():
print(f"\n>>> {random.choice(QUOTES)}\n")
def uhrzeit_anzeigen():
j = datetime.now()
print(f">>> {j.strftime('%H:%M:%S')} โ {j.strftime('%d.%m.%Y')}")
# โโ Main Menu โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def main_menu(profile):
while True:
print(f"\n{'='*35}")
print(f" PyBuddy CLI โ {profil['name']}")
print(f"{'='*35}")
print(" [1] Profile [2] XP Calculator")
print(" [3] To-Do [4] Quote")
print(" [5] Time [0] Exit")
print(f"{'='*35}")
wahl = input("Choose (0-5): ").strip()
if wahl == "0":
save_profile(profile)
print(f"Saved. Goodbye, {profil['name']}!")
break
elif wahl == "1": show_status(profile)
elif wahl == "2": xp_calculator(profile)
elif wahl == "3": todo_manager(profil)
elif wahl == "4": zufalls_zitat()
elif wahl == "5": uhrzeit_anzeigen()
else: print("Invalid. Please enter 0-5.")
# โโ Start โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def main():
print("=== PyBuddy CLI ===")
profil = load_profile()
if not profil["name"]:
profil["name"] = input("What is your name? ").strip()
print(f"Hello {profil['name']}!")
save_profile(profile)
else:
print(f"Welcome back, {profil['name']}!")
main_menu(profile)
if __name__ == "__main__":
main()
Extension Ideas
Your PyBuddy CLI is finished โ but you can expand it further. Here are ideas you can implement with the chapter concepts:
requests (Chapter 11)matplotlibrandom๐ Congratulations!
You have completed all 13 chapters and built a complete Python program. That is more than many programmers accomplish in their first month. Your PyBuddy CLI uses variables, conditions, loops, lists, dictionaries, functions, modules and file I/O โ all in one project. Show it to your friends, expand it further and above all: Keep coding!