#!/usr/bin/env python3

import math
import sys
import datetime

# ============================================================
# SAFE EVALUATOR (Prevents scientific notation exploits)
# ============================================================

def safe_eval(expr):
    """
    Safely evaluate math expressions without allowing scientific notation exploits,
    huge exponents, or malicious input.
    """
    if "e" in expr.lower():
        raise ValueError("Scientific notation is not allowed.")

    allowed = "0123456789+-*/(). "
    for ch in expr:
        if ch not in allowed:
            raise ValueError("Invalid character detected.")

    try:
        result = eval(expr, {"__builtins__": None}, {})
    except Exception:
        raise ValueError("Invalid math expression.")

    if isinstance(result, (int, float)) and abs(result) > 10**50:
        raise OverflowError("Result too large.")

    return result


# ============================================================
# INPUT HELPERS
# ============================================================

def get_float(prompt):
    while True:
        try:
            value = input(prompt).strip()
            if value.lower() == "exit":
                return None
            return float(value)
        except ValueError:
            print("Invalid number. Try again or type 'exit'.")


def get_int(prompt):
    while True:
        try:
            value = input(prompt).strip()
            if value.lower() == "exit":
                return None
            return int(value)
        except ValueError:
            print("Invalid integer. Try again or type 'exit'.")


# ============================================================
# CORE CALCULATORS
# ============================================================

def basic_math():
    expr = input("Enter math expression (or 'exit'): ").strip()
    if expr.lower() == "exit":
        return
    try:
        print("Result:", safe_eval(expr))
    except Exception as e:
        print("Error:", e)

def add():
    a = get_float("A: "); b = get_float("B: ")
    if a is None or b is None: return
    print("Sum:", a + b)

def subtract():
    a = get_float("A: "); b = get_float("B: ")
    if a is None or b is None: return
    print("Difference:", a - b)

def multiply():
    a = get_float("A: "); b = get_float("B: ")
    if a is None or b is None: return
    print("Product:", a * b)

def divide():
    a = get_float("A: "); b = get_float("B: ")
    if a is None or b is None: return
    if b == 0:
        print("Cannot divide by zero.")
        return
    print("Quotient:", a / b)

def power():
    a = get_float("Base: "); b = get_float("Exponent: ")
    if a is None or b is None: return
    print("Result:", a ** b)

def square_root():
    a = get_float("Number: ")
    if a is None: return
    if a < 0:
        print("Cannot sqrt negative.")
        return
    print("Square Root:", math.sqrt(a))

def circle_area():
    r = get_float("Radius: ")
    if r is None: return
    print("Area:", math.pi * r * r)

def circle_circumference():
    r = get_float("Radius: ")
    if r is None: return
    print("Circumference:", 2 * math.pi * r)

def bmi():
    w = get_float("Weight (kg): "); h = get_float("Height (m): ")
    if w is None or h is None: return
    print("BMI:", w / (h * h))

def tip_calc():
    bill = get_float("Bill amount: "); pct = get_float("Tip %: ")
    if bill is None or pct is None: return
    print("Tip:", bill * (pct / 100))

def loan_payment():
    P = get_float("Loan amount: ")
    r = get_float("Annual interest rate (%): ")
    n = get_int("Years: ")
    if None in (P, r, n): return
    monthly_rate = (r / 100) / 12
    months = n * 12
    if monthly_rate == 0:
        print("Payment:", P / months)
        return
    payment = P * (monthly_rate * (1 + monthly_rate)**months) / ((1 + monthly_rate)**months - 1)
    print("Monthly Payment:", payment)

def compound_interest():
    P = get_float("Principal: ")
    r = get_float("Rate (%): ")
    t = get_float("Years: ")
    n = get_int("Compounds per year: ")
    if None in (P, r, t, n): return
    A = P * (1 + (r/100)/n)**(n*t)
    print("Final Amount:", A)

def age_calc():
    year = get_int("Birth year: ")
    if year is None: return
    now = datetime.datetime.now().year
    print("Age:", now - year)

def gpa_calc():
    total = get_float("Total grade points: ")
    credits = get_float("Total credits: ")
    if None in (total, credits): return
    print("GPA:", total / credits)

def rectangle_area():
    w = get_float("Width: "); h = get_float("Height: ")
    if None in (w, h): return
    print("Area:", w * h)

def triangle_area():
    b = get_float("Base: "); h = get_float("Height: ")
    if None in (b, h): return
    print("Area:", 0.5 * b * h)

def speed_calc():
    d = get_float("Distance: "); t = get_float("Time: ")
    if None in (d, t): return
    print("Speed:", d / t)

def temperature_convert():
    print("1) C → F")
    print("2) F → C")
    choice = input("Choice: ").strip()
    if choice == "1":
        c = get_float("Celsius: ")
        if c is None: return
        print("Fahrenheit:", (c * 9/5) + 32)
    elif choice == "2":
        f = get_float("Fahrenheit: ")
        if f is None: return
        print("Celsius:", (f - 32) * 5/9)

def percent_change():
    old = get_float("Old value: "); new = get_float("New value: ")
    if None in (old, new): return
    print("Percent Change:", ((new - old) / old) * 100)

def factorial_calc():
    n = get_int("Number: ")
    if n is None: return
    if n < 0:
        print("Cannot factorial negative.")
        return
    print("Factorial:", math.factorial(n))

def quadratic_solver():
    a = get_float("a: "); b = get_float("b: "); c = get_float("c: ")
    if None in (a, b, c): return
    disc = b*b - 4*a*c
    if disc < 0:
        print("No real roots.")
        return
    r1 = (-b + math.sqrt(disc)) / (2*a)
    r2 = (-b - math.sqrt(disc)) / (2*a)
    print("Roots:", r1, r2)

def paint_needed():
    area = get_float("Wall area (sq ft): ")
    if area is None: return
    print("Gallons needed:", area / 350)

def mortgage_calc():
    loan_payment()

def time_convert():
    sec = get_int("Seconds: ")
    if sec is None: return
    print("Minutes:", sec / 60)
    print("Hours:", sec / 3600)

def prime_check():
    n = get_int("Number: ")
    if n is None: return
    if n < 2:
        print("Not prime.")
        return
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            print("Not prime.")
            return
    print("Prime.")

def simple_interest():
    P = get_float("Principal: "); r = get_float("Rate (%): "); t = get_float("Years: ")
    if None in (P, r, t): return
    print("Interest:", P * (r/100) * t)

def perimeter_rectangle():
    w = get_float("Width: "); h = get_float("Height: ")
    if None in (w, h): return
    print("Perimeter:", 2*(w+h))


# ============================================================
# EXTRA CALCULATORS (to exceed 100 total)
# ============================================================

def cube_volume():
    a = get_float("Edge length: ")
    if a is None: return
    print("Volume:", a**3)

def cylinder_volume():
    r = get_float("Radius: "); h = get_float("Height: ")
    if None in (r, h): return
    print("Volume:", math.pi * r*r * h)

def sphere_volume():
    r = get_float("Radius: ")
    if r is None: return
    print("Volume:", (4/3) * math.pi * r**3)

def sphere_surface_area():
    r = get_float("Radius: ")
    if r is None: return
    print("Surface Area:", 4 * math.pi * r**2)

def triangle_perimeter():
    a = get_float("Side a: "); b = get_float("Side b: "); c = get_float("Side c: ")
    if None in (a, b, c): return
    print("Perimeter:", a + b + c)

def square_perimeter():
    a = get_float("Side: ")
    if a is None: return
    print("Perimeter:", 4 * a)

def cube_surface_area():
    a = get_float("Edge length: ")
    if a is None: return
    print("Surface Area:", 6 * a*a)

def cylinder_surface_area():
    r = get_float("Radius: "); h = get_float("Height: ")
    if None in (r, h): return
    print("Surface Area:", 2 * math.pi * r*h + 2 * math.pi * r*r)

def pythagorean_calc():
    a = get_float("Leg a: "); b = get_float("Leg b: ")
    if None in (a, b): return
    print("Hypotenuse:", math.sqrt(a*a + b*b))

def distance_2d():
    x1 = get_float("x1: "); y1 = get_float("y1: ")
    x2 = get_float("x2: "); y2 = get_float("y2: ")
    if None in (x1, y1, x2, y2): return
    print("Distance:", math.sqrt((x2-x1)**2 + (y2-y1)**2))

def percentage_of():
    total = get_float("Total: "); pct = get_float("Percent (%): ")
    if None in (total, pct): return
    print("Result:", total * (pct/100))

def percentage_from_part():
    part = get_float("Part: "); total = get_float("Total: ")
    if None in (part, total): return
    print("Percent:", (part / total) * 100)

def discount_price():
    price = get_float("Original price: "); pct = get_float("Discount %: ")
    if None in (price, pct): return
    print("Discounted price:", price * (1 - pct/100))

def markup_price():
    cost = get_float("Cost: "); pct = get_float("Markup %: ")
    if None in (cost, pct): return
    print("Selling price:", cost * (1 + pct/100))

def profit_calc():
    revenue = get_float("Revenue: "); cost = get_float("Cost: ")
    if None in (revenue, cost): return
    print("Profit:", revenue - cost)

def break_even_units():
    fixed = get_float("Fixed cost: ")
    price = get_float("Unit price: ")
    var = get_float("Variable cost per unit: ")
    if None in (fixed, price, var): return
    if price <= var:
        print("No break-even (price <= variable cost).")
        return
    print("Break-even units:", fixed / (price - var))

def hourly_wage_from_salary():
    salary = get_float("Annual salary: ")
    hours = get_float("Hours per week: ")
    if None in (salary, hours): return
    print("Hourly wage:", salary / (hours * 52))

def salary_from_hourly():
    hourly = get_float("Hourly wage: ")
    hours = get_float("Hours per week: ")
    if None in (hourly, hours): return
    print("Annual salary:", hourly * hours * 52)

def fuel_efficiency_mpg():
    miles = get_float("Miles driven: ")
    gallons = get_float("Gallons used: ")
    if None in (miles, gallons): return
    print("MPG:", miles / gallons)

def fuel_efficiency_l_per_100km():
    liters = get_float("Liters used: ")
    km = get_float("Kilometers driven: ")
    if None in (liters, km): return
    print("L/100km:", (liters / km) * 100)

def currency_convert_simple():
    amount = get_float("Amount: ")
    rate = get_float("Conversion rate: ")
    if None in (amount, rate): return
    print("Converted:", amount * rate)

def time_difference_hours():
    h1 = get_float("Start hour (0-23): ")
    h2 = get_float("End hour (0-23): ")
    if None in (h1, h2): return
    print("Difference (hours):", h2 - h1)

def days_to_weeks():
    d = get_float("Days: ")
    if d is None: return
    print("Weeks:", d / 7)

def weeks_to_days():
    w = get_float("Weeks: ")
    if w is None: return
    print("Days:", w * 7)

def circle_sector_area():
    r = get_float("Radius: ")
    angle = get_float("Angle (degrees): ")
    if None in (r, angle): return
    print("Sector area:", math.pi * r*r * (angle / 360))

def trapezoid_area():
    a = get_float("Base a: ")
    b = get_float("Base b: ")
    h = get_float("Height: ")
    if None in (a, b, h): return
    print("Area:", (a + b) * h / 2)

def parallelogram_area():
    b = get_float("Base: ")
    h = get_float("Height: ")
    if None in (b, h): return
    print("Area:", b * h)

def regular_polygon_area():
    n = get_int("Number of sides: ")
    s = get_float("Side length: ")
    if None in (n, s): return
    print("Approx area:", (n * s*s) / (4 * math.tan(math.pi/n)))

def radians_to_degrees():
    r = get_float("Radians: ")
    if r is None: return
    print("Degrees:", r * 180 / math.pi)

def degrees_to_radians():
    d = get_float("Degrees: ")
    if d is None: return
    print("Radians:", d * math.pi / 180)

def sin_calc():
    d = get_float("Angle (degrees): ")
    if d is None: return
    print("sin:", math.sin(d * math.pi / 180))

def cos_calc():
    d = get_float("Angle (degrees): ")
    if d is None: return
    print("cos:", math.cos(d * math.pi / 180))

def tan_calc():
    d = get_float("Angle (degrees): ")
    if d is None: return
    print("tan:", math.tan(d * math.pi / 180))

def log10_calc():
    x = get_float("Number: ")
    if x is None or x <= 0:
        print("Must be > 0.")
        return
    print("log10:", math.log10(x))

def ln_calc():
    x = get_float("Number: ")
    if x is None or x <= 0:
        print("Must be > 0.")
        return
    print("ln:", math.log(x))

def exponential_calc():
    x = get_float("Exponent: ")
    if x is None: return
    print("e^x:", math.exp(x))

def harmonic_mean_two():
    a = get_float("A: "); b = get_float("B: ")
    if None in (a, b): return
    print("Harmonic mean:", 2 / (1/a + 1/b))

def geometric_mean_two():
    a = get_float("A: "); b = get_float("B: ")
    if None in (a, b): return
    print("Geometric mean:", math.sqrt(a*b))

def arithmetic_mean_two():
    a = get_float("A: "); b = get_float("B: ")
    if None in (a, b): return
    print("Arithmetic mean:", (a + b) / 2)

def body_surface_area_simple():
    w = get_float("Weight (kg): ")
    h = get_float("Height (cm): ")
    if None in (w, h): return
    print("BSA (Mosteller):", math.sqrt((h * w) / 3600))

def calorie_burn_simple():
    mets = get_float("MET value: ")
    w = get_float("Weight (kg): ")
    t = get_float("Time (hours): ")
    if None in (mets, w, t): return
    print("Calories burned:", mets * w * t)

def pace_per_km():
    time_min = get_float("Total time (minutes): ")
    distance_km = get_float("Distance (km): ")
    if None in (time_min, distance_km): return
    print("Pace (min/km):", time_min / distance_km)

def pace_per_mile():
    time_min = get_float("Total time (minutes): ")
    distance_miles = get_float("Distance (miles): ")
    if None in (time_min, distance_miles): return
    print("Pace (min/mile):", time_min / distance_miles)

def interest_rate_from_growth():
    start = get_float("Start value: ")
    end = get_float("End value: ")
    years = get_float("Years: ")
    if None in (start, end, years): return
    if start <= 0 or years <= 0:
        print("Invalid inputs.")
        return
    print("Annual rate (%):", ((end/start)**(1/years) - 1) * 100)

def doubling_time_rule_72():
    rate = get_float("Rate (%): ")
    if rate is None or rate <= 0:
        print("Invalid rate.")
        return
    print("Approx doubling time (years):", 72 / rate)

def loan_principal_from_payment():
    payment = get_float("Monthly payment: ")
    r = get_float("Annual interest rate (%): ")
    n = get_int("Years: ")
    if None in (payment, r, n): return
    monthly_rate = (r / 100) / 12
    months = n * 12
    if monthly_rate == 0:
        print("Principal:", payment * months)
        return
    principal = payment * ((1 + monthly_rate)**months - 1) / (monthly_rate * (1 + monthly_rate)**months)
    print("Principal:", principal)

def loan_term_from_payment():
    principal = get_float("Principal: ")
    r = get_float("Annual interest rate (%): ")
    payment = get_float("Monthly payment: ")
    if None in (principal, r, payment): return
    monthly_rate = (r / 100) / 12
    if monthly_rate == 0:
        print("Months:", principal / payment)
        return
    try:
        months = math.log(payment / (payment - monthly_rate * principal)) / math.log(1 + monthly_rate)
        print("Months:", months)
    except ValueError:
        print("Invalid combination (payment too small).")

def savings_future_value():
    deposit = get_float("Monthly deposit: ")
    r = get_float("Annual interest rate (%): ")
    n = get_int("Years: ")
    if None in (deposit, r, n): return
    monthly_rate = (r / 100) / 12
    months = n * 12
    if monthly_rate == 0:
        print("Future value:", deposit * months)
        return
    fv = deposit * ((1 + monthly_rate)**months - 1) / monthly_rate
    print("Future value:", fv)

def savings_required_deposit():
    goal = get_float("Goal amount: ")
    r = get_float("Annual interest rate (%): ")
    n = get_int("Years: ")
    if None in (goal, r, n): return
    monthly_rate = (r / 100) / 12
    months = n * 12
    if monthly_rate == 0:
        print("Required monthly deposit:", goal / months)
        return
    deposit = goal * monthly_rate / ((1 + monthly_rate)**months - 1)
    print("Required monthly deposit:", deposit)

def ratio_simplify_two():
    a = get_int("A: ")
    b = get_int("B: ")
    if None in (a, b): return
    def gcd(x, y):
        while y:
            x, y = y, x % y
        return x
    g = gcd(abs(a), abs(b))
    print("Simplified ratio:", a//g, ":", b//g)

def percentage_difference():
    a = get_float("A: ")
    b = get_float("B: ")
    if None in (a, b): return
    print("Percent difference:", abs(a-b) / ((a+b)/2) * 100)

def average_speed_two_segments():
    d1 = get_float("Distance 1: ")
    t1 = get_float("Time 1: ")
    d2 = get_float("Distance 2: ")
    t2 = get_float("Time 2: ")
    if None in (d1, t1, d2, t2): return
    print("Average speed:", (d1 + d2) / (t1 + t2))

def weighted_average_two():
    v1 = get_float("Value 1: ")
    w1 = get_float("Weight 1: ")
    v2 = get_float("Value 2: ")
    w2 = get_float("Weight 2: ")
    if None in (v1, w1, v2, w2): return
    print("Weighted average:", (v1*w1 + v2*w2) / (w1 + w2))

def simple_probability():
    favorable = get_float("Favorable outcomes: ")
    total = get_float("Total outcomes: ")
    if None in (favorable, total): return
    print("Probability:", favorable / total)

def combinations_n_k():
    n = get_int("n: ")
    k = get_int("k: ")
    if None in (n, k): return
    if k < 0 or n < 0 or k > n:
        print("Invalid n,k.")
        return
    print("C(n,k):", math.comb(n, k))

def permutations_n_k():
    n = get_int("n: ")
    k = get_int("k: ")
    if None in (n, k): return
    if k < 0 or n < 0 or k > n:
        print("Invalid n,k.")
        return
    print("P(n,k):", math.perm(n, k))

def simple_z_score():
    x = get_float("Value x: ")
    mean = get_float("Mean: ")
    sd = get_float("Std dev: ")
    if None in (x, mean, sd): return
    if sd == 0:
        print("Std dev cannot be 0.")
        return
    print("z-score:", (x - mean) / sd)

def unit_convert_km_miles():
    km = get_float("Kilometers: ")
    if km is None: return
    print("Miles:", km * 0.621371)

def unit_convert_miles_km():
    miles = get_float("Miles: ")
    if miles is None: return
    print("Kilometers:", miles / 0.621371)

def unit_convert_kg_lb():
    kg = get_float("Kilograms: ")
    if kg is None: return
    print("Pounds:", kg * 2.20462)

def unit_convert_lb_kg():
    lb = get_float("Pounds: ")
    if lb is None: return
    print("Kilograms:", lb / 2.20462)

def unit_convert_cm_in():
    cm = get_float("Centimeters: ")
    if cm is None: return
    print("Inches:", cm / 2.54)

def unit_convert_in_cm():
    inch = get_float("Inches: ")
    if inch is None: return
    print("Centimeters:", inch * 2.54)

def unit_convert_liters_gallons():
    l = get_float("Liters: ")
    if l is None: return
    print("Gallons:", l * 0.264172)

def unit_convert_gallons_liters():
    g = get_float("Gallons: ")
    if g is None: return
    print("Liters:", g / 0.264172)

def unit_convert_m2_ft2():
    m2 = get_float("Square meters: ")
    if m2 is None: return
    print("Square feet:", m2 * 10.7639)

def unit_convert_ft2_m2():
    ft2 = get_float("Square feet: ")
    if ft2 is None: return
    print("Square meters:", ft2 / 10.7639)


# ============================================================
# MENU SYSTEM (100+ entries)
# ============================================================

calculators = [
    ("Basic Math Expression", basic_math),
    ("Addition", add),
    ("Subtraction", subtract),
    ("Multiplication", multiply),
    ("Division", divide),
    ("Power", power),
    ("Square Root", square_root),
    ("Circle Area", circle_area),
    ("Circle Circumference", circle_circumference),
    ("BMI Calculator", bmi),
    ("Tip Calculator", tip_calc),
    ("Loan Payment", loan_payment),
    ("Compound Interest", compound_interest),
    ("Age Calculator", age_calc),
    ("GPA Calculator", gpa_calc),
    ("Rectangle Area", rectangle_area),
    ("Triangle Area", triangle_area),
    ("Speed Calculator", speed_calc),
    ("Temperature Converter", temperature_convert),
    ("Percent Change", percent_change),
    ("Factorial", factorial_calc),
    ("Quadratic Solver", quadratic_solver),
    ("Paint Needed", paint_needed),
    ("Mortgage Calculator", mortgage_calc),
    ("Time Converter", time_convert),
    ("Prime Checker", prime_check),
    ("Simple Interest", simple_interest),
    ("Rectangle Perimeter", perimeter_rectangle),

    # Extra geometry & trig
    ("Cube Volume", cube_volume),
    ("Cylinder Volume", cylinder_volume),
    ("Sphere Volume", sphere_volume),
    ("Sphere Surface Area", sphere_surface_area),
    ("Triangle Perimeter", triangle_perimeter),
    ("Square Perimeter", square_perimeter),
    ("Cube Surface Area", cube_surface_area),
    ("Cylinder Surface Area", cylinder_surface_area),
    ("Pythagorean Calculator", pythagorean_calc),
    ("2D Distance", distance_2d),
    ("Circle Sector Area", circle_sector_area),
    ("Trapezoid Area", trapezoid_area),
    ("Parallelogram Area", parallelogram_area),
    ("Regular Polygon Area (approx)", regular_polygon_area),
    ("Radians to Degrees", radians_to_degrees),
    ("Degrees to Radians", degrees_to_radians),
    ("sin(deg)", sin_calc),
    ("cos(deg)", cos_calc),
    ("tan(deg)", tan_calc),

    # Percent & finance
    ("Percentage Of", percentage_of),
    ("Percent from Part/Total", percentage_from_part),
    ("Discount Price", discount_price),
    ("Markup Price", markup_price),
    ("Profit Calculator", profit_calc),
    ("Break-even Units", break_even_units),
    ("Hourly Wage from Salary", hourly_wage_from_salary),
    ("Salary from Hourly Wage", salary_from_hourly),
    ("Fuel Efficiency MPG", fuel_efficiency_mpg),
    ("Fuel Efficiency L/100km", fuel_efficiency_l_per_100km),
    ("Simple Currency Convert", currency_convert_simple),
    ("Interest Rate from Growth", interest_rate_from_growth),
    ("Doubling Time (Rule of 72)", doubling_time_rule_72),
    ("Loan Principal from Payment", loan_principal_from_payment),
    ("Loan Term from Payment", loan_term_from_payment),
    ("Savings Future Value", savings_future_value),
    ("Savings Required Deposit", savings_required_deposit),

    # Time & ratios
    ("Time Difference (hours)", time_difference_hours),
    ("Days to Weeks", days_to_weeks),
    ("Weeks to Days", weeks_to_days),
    ("Simplify Ratio (A:B)", ratio_simplify_two),
    ("Percent Difference", percentage_difference),
    ("Average Speed (2 segments)", average_speed_two_segments),
    ("Weighted Average (2 values)", weighted_average_two),

    # Stats & probability
    ("Simple Probability", simple_probability),
    ("Combinations nCk", combinations_n_k),
    ("Permutations nPk", permutations_n_k),
    ("Simple z-score", simple_z_score),

    # Logs & exponentials
    ("log10(x)", log10_calc),
    ("ln(x)", ln_calc),
    ("e^x", exponential_calc),
    ("Harmonic Mean (2)", harmonic_mean_two),
    ("Geometric Mean (2)", geometric_mean_two),
    ("Arithmetic Mean (2)", arithmetic_mean_two),

    # Health & fitness
    ("Body Surface Area (Mosteller)", body_surface_area_simple),
    ("Calorie Burn (simple MET)", calorie_burn_simple),
    ("Running Pace (min/km)", pace_per_km),
    ("Running Pace (min/mile)", pace_per_mile),

    # Unit conversions
    ("Convert km → miles", unit_convert_km_miles),
    ("Convert miles → km", unit_convert_miles_km),
    ("Convert kg → lb", unit_convert_kg_lb),
    ("Convert lb → kg", unit_convert_lb_kg),
    ("Convert cm → in", unit_convert_cm_in),
    ("Convert in → cm", unit_convert_in_cm),
    ("Convert liters → gallons", unit_convert_liters_gallons),
    ("Convert gallons → liters", unit_convert_gallons_liters),
    ("Convert m² → ft²", unit_convert_m2_ft2),
    ("Convert ft² → m²", unit_convert_ft2_m2),
]

def main():
    while True:
        print("\n=== MEGA CALCULATOR HUB (94+ tools) ===")
        for i, (name, _) in enumerate(calculators, start=1):
            print(f"{i}) {name}")
        print("0) Exit Program")

        choice = input("Choose: ").strip()

        if choice == "0":
            print("Goodbye!")
            sys.exit(0)

        if not choice.isdigit():
            print("Invalid choice.")
            continue

        idx = int(choice) - 1
        if 0 <= idx < len(calculators):
            calculators[idx][1]()
        else:
            print("Invalid selection.")

if __name__ == "__main__":
    main()

