Blog Pages

Secure Notes App

 import os

import tkinter as tk

from tkinter import messagebox, simpledialog

from cryptography.fernet import Fernet


# Generate a key file if it doesn’t exist

KEY_FILE = "secret.key"

NOTES_FILE = "secure_notes.txt"


def generate_key():

    key = Fernet.generate_key()

    with open(KEY_FILE, "wb") as key_file:

        key_file.write(key)


def load_key():

    if not os.path.exists(KEY_FILE):

        generate_key()

    with open(KEY_FILE, "rb") as key_file:

        return key_file.read()


# Load encryption key

key = load_key()

cipher_suite = Fernet(key)


def encrypt_message(message):

    return cipher_suite.encrypt(message.encode()).decode()


def decrypt_message(encrypted_message):

    return cipher_suite.decrypt(encrypted_message.encode()).decode()


def save_note():

    note = note_text.get("1.0", tk.END).strip()

    if not note:

        messagebox.showwarning("Warning", "Note cannot be empty!")

        return

    

    encrypted_note = encrypt_message(note)

    with open(NOTES_FILE, "a") as file:

        file.write(encrypted_note + "\n")

    

    messagebox.showinfo("Success", "Note saved securely!")

    note_text.delete("1.0", tk.END)


def load_notes():

    if not os.path.exists(NOTES_FILE):

        messagebox.showinfo("No Notes", "No saved notes found.")

        return

    

    with open(NOTES_FILE, "r") as file:

        encrypted_notes = file.readlines()

    

    if not encrypted_notes:

        messagebox.showinfo("No Notes", "No saved notes found.")

        return


    password = simpledialog.askstring("Password", "Enter decryption password:", show="*")

    

    if password:  # Dummy check

        try:

            decrypted_notes = [decrypt_message(note.strip()) for note in encrypted_notes]

            messagebox.showinfo("Your Notes", "\n\n".join(decrypted_notes))

        except Exception as e:

            messagebox.showerror("Error", "Failed to decrypt notes.")

    else:

        messagebox.showwarning("Warning", "Password cannot be empty!")


# GUI Setup

root = tk.Tk()

root.title("Secure Notes App")

root.geometry("400x400")


tk.Label(root, text="Enter your note:", font=("Arial", 12)).pack(pady=5)

note_text = tk.Text(root, height=8, width=40)

note_text.pack()


save_btn = tk.Button(root, text="Save Note", command=save_note)

save_btn.pack(pady=5)


load_btn = tk.Button(root, text="Load Notes", command=load_notes)

load_btn.pack(pady=5)


root.mainloop()


Password Manager

 import sqlite3

import tkinter as tk

from tkinter import messagebox

from cryptography.fernet import Fernet

import random

import string

import os


# Generate and save encryption key

KEY_FILE = "key.key"


def generate_key():

    if not os.path.exists(KEY_FILE):

        key = Fernet.generate_key()

        with open(KEY_FILE, "wb") as key_file:

            key_file.write(key)


def load_key():

    with open(KEY_FILE, "rb") as key_file:

        return key_file.read()


generate_key()

key = load_key()

cipher = Fernet(key)


# Database Setup

conn = sqlite3.connect("passwords.db")

cursor = conn.cursor()

cursor.execute("""

    CREATE TABLE IF NOT EXISTS passwords (

        id INTEGER PRIMARY KEY,

        website TEXT,

        username TEXT,

        password TEXT

    )

""")

conn.commit()


# Function to encrypt password

def encrypt_password(password):

    return cipher.encrypt(password.encode()).decode()


# Function to decrypt password

def decrypt_password(encrypted_password):

    return cipher.decrypt(encrypted_password.encode()).decode()


# Function to generate a random password

def generate_password():

    characters = string.ascii_letters + string.digits + string.punctuation

    return ''.join(random.choice(characters) for _ in range(12))


# Function to save credentials

def save_password():

    website = website_entry.get()

    username = username_entry.get()

    password = password_entry.get()


    if not website or not username or not password:

        messagebox.showerror("Error", "All fields are required!")

        return


    encrypted_password = encrypt_password(password)

    cursor.execute("INSERT INTO passwords (website, username, password) VALUES (?, ?, ?)",

                   (website, username, encrypted_password))

    conn.commit()

    messagebox.showinfo("Success", "Password saved successfully!")


    website_entry.delete(0, tk.END)

    username_entry.delete(0, tk.END)

    password_entry.delete(0, tk.END)


# Function to retrieve passwords

def retrieve_passwords():

    cursor.execute("SELECT website, username, password FROM passwords")

    records = cursor.fetchall()


    result_text.delete(1.0, tk.END)

    for record in records:

        website, username, encrypted_password = record

        decrypted_password = decrypt_password(encrypted_password)

        result_text.insert(tk.END, f"Website: {website}\nUsername: {username}\nPassword: {decrypted_password}\n\n")


# Function to generate a random password

def fill_generated_password():

    password_entry.delete(0, tk.END)

    password_entry.insert(0, generate_password())


# GUI Setup

root = tk.Tk()

root.title("Password Manager")

root.geometry("400x500")


tk.Label(root, text="Website:").pack()

website_entry = tk.Entry(root, width=40)

website_entry.pack()


tk.Label(root, text="Username:").pack()

username_entry = tk.Entry(root, width=40)

username_entry.pack()


tk.Label(root, text="Password:").pack()

password_entry = tk.Entry(root, width=40, show="*")

password_entry.pack()


tk.Button(root, text="Generate Password", command=fill_generated_password).pack(pady=5)

tk.Button(root, text="Save Password", command=save_password).pack(pady=5)

tk.Button(root, text="Retrieve Passwords", command=retrieve_passwords).pack(pady=5)


result_text = tk.Text(root, height=10, width=45)

result_text.pack()


root.mainloop()


Book Tracker

 import sqlite3

from tkinter import Tk, Label, Entry, Button, ttk, messagebox


# Database setup

def setup_database():

    conn = sqlite3.connect('books.db')

    cursor = conn.cursor()

    cursor.execute("""

        CREATE TABLE IF NOT EXISTS books (

            id INTEGER PRIMARY KEY AUTOINCREMENT,

            title TEXT NOT NULL,

            author TEXT NOT NULL,

            status TEXT NOT NULL

        )

    """)

    conn.commit()

    conn.close()


# Add book

def add_book(title, author, status):

    if not title or not author or not status:

        messagebox.showerror("Error", "All fields are required.")

        return

    conn = sqlite3.connect('books.db')

    cursor = conn.cursor()

    cursor.execute("INSERT INTO books (title, author, status) VALUES (?, ?, ?)", (title, author, status))

    conn.commit()

    conn.close()

    messagebox.showinfo("Success", "Book added successfully!")

    refresh_list()


# Get books

def get_books():

    conn = sqlite3.connect('books.db')

    cursor = conn.cursor()

    cursor.execute("SELECT id, title, author, status FROM books")

    books = cursor.fetchall()

    conn.close()

    return books


# Update book status

def update_status(book_id, new_status):

    conn = sqlite3.connect('books.db')

    cursor = conn.cursor()

    cursor.execute("UPDATE books SET status = ? WHERE id = ?", (new_status, book_id))

    conn.commit()

    conn.close()

    messagebox.showinfo("Success", "Book status updated successfully!")

    refresh_list()


# Delete book

def delete_book(book_id):

    conn = sqlite3.connect('books.db')

    cursor = conn.cursor()

    cursor.execute("DELETE FROM books WHERE id = ?", (book_id,))

    conn.commit()

    conn.close()

    messagebox.showinfo("Success", "Book deleted successfully!")

    refresh_list()


# Refresh the book list in the GUI

def refresh_list():

    for row in tree.get_children():

        tree.delete(row)

    books = get_books()

    for book in books:

        tree.insert("", "end", values=book)


# GUI setup

def setup_gui():

    global tree

    root = Tk()

    root.title("Book Tracker")


    # Labels and input fields

    Label(root, text="Title:").grid(row=0, column=0, padx=5, pady=5)

    title_entry = Entry(root)

    title_entry.grid(row=0, column=1, padx=5, pady=5)


    Label(root, text="Author:").grid(row=1, column=0, padx=5, pady=5)

    author_entry = Entry(root)

    author_entry.grid(row=1, column=1, padx=5, pady=5)


    Label(root, text="Status:").grid(row=2, column=0, padx=5, pady=5)

    status_combobox = ttk.Combobox(root, values=["To Read", "Reading", "Finished"])

    status_combobox.grid(row=2, column=1, padx=5, pady=5)


    # Buttons

    Button(root, text="Add Book", command=lambda: add_book(title_entry.get(), author_entry.get(), status_combobox.get())).grid(row=3, column=0, columnspan=2, pady=10)


    # Book list

    columns = ("ID", "Title", "Author", "Status")

    tree = ttk.Treeview(root, columns=columns, show="headings")

    for col in columns:

        tree.heading(col, text=col)

        tree.column(col, width=150)

    tree.grid(row=4, column=0, columnspan=2, padx=5, pady=5)


    # Actions

    Button(root, text="Update Status", command=lambda: update_status(tree.item(tree.focus())['values'][0], status_combobox.get())).grid(row=5, column=0, pady=10)

    Button(root, text="Delete Book", command=lambda: delete_book(tree.item(tree.focus())['values'][0])).grid(row=5, column=1, pady=10)


    refresh_list()

    root.mainloop()


if __name__ == "__main__":

    setup_database()

    setup_gui()


Python is TIOBE's programming language of the year 2024!

 TIOBE Index for January 2025

January Headline: Python is TIOBE's programming language of the year 2024!

Programming language Python has won the title "TIOBE's programming language of the year 2024". This award is given to the programming language with the highest increase in ratings in one year time. Python gained a whopping 9.3% in 2024. This is far ahead of its competition: Java +2.3%, JavaScript +1.4% and Go +1.2%. Python is everywhere nowadays, and it is the undisputed default language of choice in many fields. It might even become the language with the highest ranking ever in the TIOBE index. Python's only serious drawbacks are (and thus leaving room for competition) its lack of performance and that most errors occur run-time.

For More Information   https://www.tiobe.com/tiobe-index/

Pomodoro Timer

 import tkinter as tk

from tkinter import messagebox

import time


# Constants

WORK_MIN = 25  # Work duration in minutes

SHORT_BREAK_MIN = 5  # Short break duration in minutes

LONG_BREAK_MIN = 15  # Long break duration in minutes

CYCLES = 4  # Number of work sessions before a long break


class PomodoroTimer:

    def __init__(self):

        self.root = tk.Tk()

        self.root.title("Pomodoro Timer")

        self.timer_running = False

        self.current_cycle = 0

        self.time_left = 0


        # UI Setup

        self.label = tk.Label(self.root, text="Pomodoro Timer", font=("Arial", 20))

        self.label.pack(pady=10)


        self.time_label = tk.Label(self.root, text="00:00", font=("Arial", 40))

        self.time_label.pack(pady=10)


        self.start_button = tk.Button(self.root, text="Start", font=("Arial", 15), command=self.start_timer)

        self.start_button.pack(side="left", padx=10)


        self.reset_button = tk.Button(self.root, text="Reset", font=("Arial", 15), command=self.reset_timer)

        self.reset_button.pack(side="right", padx=10)


    def start_timer(self):

        if not self.timer_running:

            self.current_cycle += 1

            if self.current_cycle % (CYCLES + 1) == 0:

                self.time_left = LONG_BREAK_MIN * 60

                self.label.config(text="Long Break", fg="blue")

            elif self.current_cycle % 2 == 0:

                self.time_left = SHORT_BREAK_MIN * 60

                self.label.config(text="Short Break", fg="green")

            else:

                self.time_left = WORK_MIN * 60

                self.label.config(text="Work", fg="red")


            self.timer_running = True

            self.countdown()


    def countdown(self):

        if self.time_left > 0:

            mins, secs = divmod(self.time_left, 60)

            self.time_label.config(text=f"{mins:02}:{secs:02}")

            self.time_left -= 1

            self.root.after(1000, self.countdown)

        else:

            self.timer_running = False

            self.time_label.config(text="00:00")

            if self.current_cycle % 2 != 0:

                messagebox.showinfo("Time's up!", "Time for a break!")

            else:

                messagebox.showinfo("Time's up!", "Time to work!")


    def reset_timer(self):

        self.timer_running = False

        self.current_cycle = 0

        self.time_left = 0

        self.label.config(text="Pomodoro Timer", fg="black")

        self.time_label.config(text="00:00")


    def run(self):

        self.root.mainloop()


# Run the Pomodoro Timer

if __name__ == "__main__":

    PomodoroTimer().run()


News Aggregator


  • Visit NewsAPI and sign up for a free API key.
  • Replace your_newsapi_key in the code with your actual API key.

  •  import requests

    API_KEY = "your_newsapi_key"  # Replace with your NewsAPI key

    BASE_URL = "https://newsapi.org/v2/"


    def fetch_top_headlines(country="us", category="general", page_size=5):

        """

        Fetch top news headlines from NewsAPI.

        Args:

            country (str): Country code for news (default is 'us').

            category (str): Category of news (default is 'general').

            page_size (int): Number of headlines to fetch (default is 5).

        Returns:

            list: A list of dictionaries containing news headlines and details.

        """

        url = f"{BASE_URL}top-headlines"

        params = {

            "apiKey": API_KEY,

            "country": country,

            "category": category,

            "pageSize": page_size,

        }

        try:

            response = requests.get(url, params=params)

            response.raise_for_status()

            data = response.json()

            return data.get("articles", [])

        except requests.exceptions.RequestException as e:

            print(f"Error fetching news: {e}")

            return []


    def display_headlines(articles):

        """

        Display news headlines in a user-friendly format.


        Args:

            articles (list): List of news articles.

        """

        if not articles:

            print("No news articles found.")

            return

        print("\n--- Latest News Headlines ---")

        for idx, article in enumerate(articles, 1):

            print(f"\n{idx}. {article['title']}")

            print(f"   Source: {article['source']['name']}")

            print(f"   URL: {article['url']}")


    def main():

        print("Welcome to the News Aggregator!")

        country = input("Enter the country code for news (e.g., 'us' for USA, 'in' for India): ").strip()

        category = input("Enter the category of news (e.g., 'business', 'entertainment', 'sports'): ").strip()

        num_articles = input("How many articles would you like to fetch? (default is 5): ").strip()


        # Default values if input is empty

        country = country if country else "us"

        category = category if category else "general"

        num_articles = int(num_articles) if num_articles.isdigit() else 5


        print("\nFetching top headlines...")

        articles = fetch_top_headlines(country=country, category=category, page_size=num_articles)


        display_headlines(articles)


    if __name__ == "__main__":

        main()


    Stock Price Tracker

     import yfinance as yf

    import matplotlib.pyplot as plt

    import pandas as pd


    def get_stock_data(ticker, period='1mo', interval='1d'):

        """

        Fetch stock data for a given ticker.


        Args:

            ticker (str): The stock ticker symbol.

            period (str): The time period for historical data (e.g., '1mo', '1y').

            interval (str): The interval for the data (e.g., '1d', '1h').


        Returns:

            pandas.DataFrame: Historical stock data.

        """

        try:

            stock = yf.Ticker(ticker)

            data = stock.history(period=period, interval=interval)

            return data

        except Exception as e:

            print(f"Error fetching data: {e}")

            return None


    def plot_stock_data(data, ticker):

        """

        Plot stock closing price data.


        Args:

            data (pandas.DataFrame): Historical stock data.

            ticker (str): The stock ticker symbol.

        """

        if data is not None and not data.empty:

            plt.figure(figsize=(10, 6))

            plt.plot(data.index, data['Close'], label=f'{ticker} Closing Price')

            plt.title(f"{ticker} Stock Price")

            plt.xlabel("Date")

            plt.ylabel("Closing Price")

            plt.legend()

            plt.grid()

            plt.show()

        else:

            print("No data available to plot.")


    def main():

        print("Welcome to the Stock Price Tracker!")

        ticker = input("Enter the stock ticker symbol (e.g., AAPL, TSLA, GOOGL): ").upper()

        period = input("Enter the time period (default is '1mo', e.g., '1d', '1y'): ") or '1mo'

        interval = input("Enter the data interval (default is '1d', e.g., '1h', '1wk'): ") or '1d'


        print("\nFetching stock data...")

        data = get_stock_data(ticker, period, interval)

        

        if data is not None and not data.empty:

            print("\nStock data fetched successfully!")

            print(data.tail())  # Display the last 5 rows of data

            plot_stock_data(data, ticker)

        else:

            print("Failed to fetch stock data. Please check the ticker symbol or try again.")


    if __name__ == "__main__":

        main()


    Color Palette Generator

     from PIL import Image

    from sklearn.cluster import KMeans

    import numpy as np

    import matplotlib.pyplot as plt


    def extract_colors(image_path, num_colors=5):

        """

        Extracts dominant colors from an image.


        Args:

            image_path (str): Path to the image file.

            num_colors (int): Number of dominant colors to extract.


        Returns:

            List of RGB tuples representing the dominant colors.

        """

        try:

            # Open the image and resize it for faster processing

            image = Image.open(image_path)

            image = image.resize((200, 200))  # Resize for faster processing

            image_array = np.array(image)


            # Reshape the image array to a 2D array of pixels

            pixels = image_array.reshape(-1, 3)


            # Apply KMeans clustering to find dominant colors

            kmeans = KMeans(n_clusters=num_colors, random_state=0)

            kmeans.fit(pixels)


            # Extract cluster centers (dominant colors)

            colors = kmeans.cluster_centers_.astype(int)

            return colors

        except Exception as e:

            print(f"Error: {e}")

            return []


    def display_palette(colors):

        """

        Displays the color palette using matplotlib.


        Args:

            colors (list): List of RGB tuples representing colors.

        """

        if colors is None or len(colors) == 0:

            print("No colors to display.")

            return


        # Create a palette image

        palette = np.zeros((50, len(colors) * 50, 3), dtype=np.uint8)

        for i, color in enumerate(colors):

            palette[:, i * 50:(i + 1) * 50, :] = color


        # Display the palette

        plt.imshow(palette)

        plt.axis("off")

        plt.show()



    def main():

        print("Welcome to the Color Palette Generator!")

        image_path = input("Enter the path to the image file: ")

        num_colors = input("Enter the number of colors to extract (default is 5): ")

        num_colors = int(num_colors) if num_colors.isdigit() else 5


        print("\nExtracting colors...")

        colors = extract_colors(image_path, num_colors)


        if len(colors) > 0:

            print("Dominant colors (RGB):")

            for i, color in enumerate(colors, 1):

                print(f"{i}: {tuple(color)}")

            display_palette(colors)


    if __name__ == "__main__":

        main()


    Image to ASCII Art

     from PIL import Image


    # Define ASCII characters for different levels of brightness

    ASCII_CHARS = ["@", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]


    def resize_image(image, new_width=100):

        """Resizes the image while maintaining aspect ratio."""

        width, height = image.size

        aspect_ratio = height / width

        new_height = int(new_width * aspect_ratio * 0.55)  # Adjusting for terminal aspect ratio

        return image.resize((new_width, new_height))


    def grayify(image):

        """Converts the image to grayscale."""

        return image.convert("L")


    def pixels_to_ascii(image):

        """Maps grayscale pixel values to ASCII characters."""

        pixels = image.getdata()

        ascii_str = "".join(ASCII_CHARS[pixel // 25] for pixel in pixels)

        return ascii_str


    def convert_image_to_ascii(image_path, new_width=100):

        """Main function to convert image to ASCII art."""

        try:

            image = Image.open(image_path)

        except Exception as e:

            print(f"Unable to open image file: {image_path}")

            print(e)

            return


        # Resize and process the image

        image = resize_image(image, new_width)

        image = grayify(image)


        # Convert pixels to ASCII

        ascii_str = pixels_to_ascii(image)

        img_width = image.width

        ascii_str_len = len(ascii_str)

        ascii_art = "\n".join(ascii_str[i:i + img_width] for i in range(0, ascii_str_len, img_width))


        return ascii_art


    def main():

        image_path = input("Enter the path to the image file: ")

        width = int(input("Enter the desired width of the ASCII art (default is 100): ") or 100)

        ascii_art = convert_image_to_ascii(image_path, width)

        

        if ascii_art:

            print("\nGenerated ASCII Art:\n")

            print(ascii_art)

            

            # Save the ASCII art to a text file

            output_file = "ascii_art.txt"

            with open(output_file, "w") as f:

                f.write(ascii_art)

            print(f"\nASCII art has been saved to {output_file}")


    if __name__ == "__main__":

        main()


    Image Resizer with a GUI

     import tkinter as tk

    from tkinter import filedialog, messagebox

    from PIL import Image, ImageTk


    def select_image():

        global img, img_path

        img_path = filedialog.askopenfilename(

            filetypes=[("Image Files", "*.jpg;*.jpeg;*.png;*.bmp;*.gif")]

        )

        if not img_path:

            return

        img = Image.open(img_path)

        preview_image(img)


    def preview_image(image):

        # Resize for preview

        preview = image.copy()

        preview.thumbnail((300, 300))

        tk_img = ImageTk.PhotoImage(preview)

        img_label.config(image=tk_img)

        img_label.image = tk_img


    def resize_image():

        global img, img_path

        if not img_path:

            messagebox.showerror("Error", "No image selected!")

            return


        try:

            new_width = int(width_entry.get())

            new_height = int(height_entry.get())

            resized_img = img.resize((new_width, new_height))

            

            save_path = filedialog.asksaveasfilename(

                defaultextension=".png",

                filetypes=[("PNG files", "*.png"), ("JPEG files", "*.jpg"), ("All files", "*.*")]

            )

            if save_path:

                resized_img.save(save_path)

                messagebox.showinfo("Success", f"Image saved to {save_path}")

        except ValueError:

            messagebox.showerror("Error", "Please enter valid width and height values!")

        except Exception as e:

            messagebox.showerror("Error", f"An error occurred: {str(e)}")


    # GUI Setup

    root = tk.Tk()

    root.title("Image Resizer")


    frame = tk.Frame(root)

    frame.pack(pady=10)


    # Image Preview

    img_label = tk.Label(frame)

    img_label.pack()


    # Select Image Button

    select_btn = tk.Button(root, text="Select Image", command=select_image)

    select_btn.pack(pady=5)


    # Input Fields for Width and Height

    size_frame = tk.Frame(root)

    size_frame.pack(pady=5)

    tk.Label(size_frame, text="Width: ").grid(row=0, column=0, padx=5)

    width_entry = tk.Entry(size_frame, width=10)

    width_entry.grid(row=0, column=1, padx=5)

    tk.Label(size_frame, text="Height: ").grid(row=0, column=2, padx=5)

    height_entry = tk.Entry(size_frame, width=10)

    height_entry.grid(row=0, column=3, padx=5)


    # Resize Button

    resize_btn = tk.Button(root, text="Resize and Save", command=resize_image)

    resize_btn.pack(pady=10)


    root.mainloop()


    Unit Converter

     def convert_temperature(value, from_unit, to_unit):

        if from_unit == "Celsius" and to_unit == "Fahrenheit":

            return (value * 9/5) + 32

        elif from_unit == "Fahrenheit" and to_unit == "Celsius":

            return (value - 32) * 5/9

        elif from_unit == "Celsius" and to_unit == "Kelvin":

            return value + 273.15

        elif from_unit == "Kelvin" and to_unit == "Celsius":

            return value - 273.15

        elif from_unit == "Fahrenheit" and to_unit == "Kelvin":

            return (value - 32) * 5/9 + 273.15

        elif from_unit == "Kelvin" and to_unit == "Fahrenheit":

            return (value - 273.15) * 9/5 + 32

        return value


    def convert_length(value, from_unit, to_unit):

        conversion_factors = {

            "meters": 1,

            "kilometers": 0.001,

            "centimeters": 100,

            "millimeters": 1000,

            "inches": 39.3701,

            "feet": 3.28084,

            "miles": 0.000621371,

        }

        return value * conversion_factors[to_unit] / conversion_factors[from_unit]


    def convert_weight(value, from_unit, to_unit):

        conversion_factors = {

            "kilograms": 1,

            "grams": 1000,

            "milligrams": 1_000_000,

            "pounds": 2.20462,

            "ounces": 35.274,

        }

        return value * conversion_factors[to_unit] / conversion_factors[from_unit]


    def main():

        print("Unit Converter")

        print("1. Temperature")

        print("2. Length")

        print("3. Weight")

        choice = input("Choose a category (1/2/3): ")


        if choice == "1":

            print("\nTemperature Units: Celsius, Fahrenheit, Kelvin")

            value = float(input("Enter the value to convert: "))

            from_unit = input("Convert from: ").capitalize()

            to_unit = input("Convert to: ").capitalize()

            result = convert_temperature(value, from_unit, to_unit)

            print(f"{value} {from_unit} is equal to {result:.2f} {to_unit}")


        elif choice == "2":

            print("\nLength Units: meters, kilometers, centimeters, millimeters, inches, feet, miles")

            value = float(input("Enter the value to convert: "))

            from_unit = input("Convert from: ").lower()

            to_unit = input("Convert to: ").lower()

            result = convert_length(value, from_unit, to_unit)

            print(f"{value} {from_unit} is equal to {result:.2f} {to_unit}")


        elif choice == "3":

            print("\nWeight Units: kilograms, grams, milligrams, pounds, ounces")

            value = float(input("Enter the value to convert: "))

            from_unit = input("Convert from: ").lower()

            to_unit = input("Convert to: ").lower()

            result = convert_weight(value, from_unit, to_unit)

            print(f"{value} {from_unit} is equal to {result:.2f} {to_unit}")


        else:

            print("Invalid choice! Please select 1, 2, or 3.")


    if __name__ == "__main__":

        main()