import streamlit as st import numpy as np import math import pandas as pd import matplotlib.pyplot as plt st.set_page_config(page_title="Advanced Calculator", layout="centered") st.title("🧮 Advanced Calculator") st.markdown("Multi-feature calculator for Hugging Face Streamlit deployment") # ------------------------------- # Safe Expression Evaluation # ------------------------------- allowed_names = { k: getattr(math, k) for k in dir(math) if not k.startswith("_") } allowed_names.update({ "np": np, "abs": abs, "round": round }) def safe_eval(expr): try: return eval(expr, {"__builtins__": {}}, allowed_names) except Exception as e: return f"Error: {e}" # ------------------------------- # Sidebar Navigation # ------------------------------- option = st.sidebar.selectbox( "Select Calculator Mode", ["Basic / Scientific", "Unit Converter", "Function Plotter", "History"] ) # Session history if "history" not in st.session_state: st.session_state.history = [] # ------------------------------- # BASIC & SCIENTIFIC CALCULATOR # ------------------------------- if option == "Basic / Scientific": st.subheader("Basic & Scientific Calculator") expr = st.text_input( "Enter mathematical expression", placeholder="Example: sin(pi/2) + log(10)" ) if st.button("Calculate"): result = safe_eval(expr) st.write("### Result:", result) st.session_state.history.append({ "Expression": expr, "Result": result }) # ------------------------------- # UNIT CONVERTER # ------------------------------- elif option == "Unit Converter": st.subheader("Unit Converter") conversion_type = st.selectbox( "Select Conversion Type", ["Length", "Weight", "Temperature"] ) value = st.number_input("Enter Value") if conversion_type == "Length": units = st.selectbox("Convert From", ["Meters", "Kilometers", "Miles"]) target = st.selectbox("Convert To", ["Meters", "Kilometers", "Miles"]) conversion = { "Meters": 1, "Kilometers": 1000, "Miles": 1609.34 } result = value * conversion[units] / conversion[target] st.write("### Result:", result) elif conversion_type == "Weight": units = st.selectbox("Convert From", ["Grams", "Kilograms", "Pounds"]) target = st.selectbox("Convert To", ["Grams", "Kilograms", "Pounds"]) conversion = { "Grams": 1, "Kilograms": 1000, "Pounds": 453.592 } result = value * conversion[units] / conversion[target] st.write("### Result:", result) elif conversion_type == "Temperature": units = st.selectbox("Convert From", ["Celsius", "Fahrenheit", "Kelvin"]) target = st.selectbox("Convert To", ["Celsius", "Fahrenheit", "Kelvin"]) def temp_convert(val, u, t): if u == t: return val # Convert to Celsius first if u == "Fahrenheit": val = (val - 32) * 5/9 elif u == "Kelvin": val = val - 273.15 # Convert from Celsius to target if t == "Fahrenheit": return val * 9/5 + 32 elif t == "Kelvin": return val + 273.15 return val st.write("### Result:", temp_convert(value, units, target)) # ------------------------------- # FUNCTION PLOTTER # ------------------------------- elif option == "Function Plotter": st.subheader("Function Plotter") func_expr = st.text_input( "Enter function in terms of x", placeholder="Example: sin(x) or x**2 + 3*x" ) x_min = st.number_input("X min", value=-10.0) x_max = st.number_input("X max", value=10.0) if st.button("Plot Function"): try: x = np.linspace(x_min, x_max, 400) y = eval(func_expr, {"__builtins__": {}}, {**allowed_names, "x": x}) fig, ax = plt.subplots() ax.plot(x, y) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_title(f"Plot of {func_expr}") ax.grid(True) st.pyplot(fig) except Exception as e: st.error(f"Plot Error: {e}") # ------------------------------- # HISTORY # ------------------------------- elif option == "History": st.subheader("Calculation History") if st.session_state.history: df = pd.DataFrame(st.session_state.history) st.dataframe(df, use_container_width=True) if st.button("Clear History"): st.session_state.history = [] else: st.info("No calculations yet.")