File size: 10,486 Bytes
761e949
 
9e39984
761e949
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e39984
 
761e949
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
import streamlit as st
import sympy as sp
from solver import solve_equation, generate_steps
from plotter import plot_function
from utils import load_css, initialize_session_state
from auth import (
    login_user, signup_user, is_logged_in, logout_user,
    update_profile, get_user_profile, change_password
)
from models import History, SessionLocal, init_db
import base64
from io import BytesIO

# Initialize database
init_db()

def save_to_history(equation: str, solution: str):
    """Save equation and solution to user's history."""
    if not is_logged_in():
        return

    db = SessionLocal()
    try:
        history = History(
            user_id=st.session_state.user_id,
            equation=equation,
            solution=solution
        )
        db.add(history)
        db.commit()
    finally:
        db.close()

def load_user_history():
    """Load user's solution history."""
    if not is_logged_in():
        return []

    db = SessionLocal()
    try:
        return db.query(History).filter(
            History.user_id == st.session_state.user_id
        ).order_by(History.created_at.desc()).all()
    finally:
        db.close()

def render_math_symbols():
    """Render mathematical symbols for input."""
    st.markdown("### Mathematical Operators")

    cols = st.columns(8)
    all_symbols = {
        # Basic arithmetic
        '×': '*',
        '÷': '/',
        '^': '^',
        '=': '=',
        '(': '(',
        ')': ')',

        # Functions and special operators
        '√': '√',
        '∫': '∫',
        'd/dx': 'd/dx',
        '!': '!',
        'ℒ': 'L',
        '∑': 'sum',
        '∏': 'prod',
        '|': '|',

        # Constants
        'π': 'pi',
        'e': 'e',
        'i': 'i',
        '∞': 'oo',

        # Trigonometric
        'sin': 'sin(',
        'cos': 'cos(',
        'tan': 'tan(',
        'csc': 'csc(',
        'sec': 'sec(',
        'cot': 'cot(',

        # Inverse trigonometric
        'sin⁻¹': 'sin⁻¹(',
        'cos⁻¹': 'cos⁻¹(',
        'tan⁻¹': 'tan⁻¹(',

        # Other functions
        'ln': 'ln(',
        'log': 'log(',
        'e^': 'e^',
        '|x|': 'abs(',
    }

    for i, (label, symbol) in enumerate(all_symbols.items()):
        col_idx = i % 8
        if cols[col_idx].button(label, key=f"btn_{label}", help=f"Insert {label}"):
            if 'equation' not in st.session_state:
                st.session_state.equation = ''
            st.session_state.equation += symbol

def render_profile_settings():
    """Render user profile settings page."""
    st.title("Profile Settings")

    user = get_user_profile(st.session_state.user_id)

    # Profile photo upload
    st.subheader("Profile Photo")
    uploaded_file = st.file_uploader("Choose a profile photo", type=['jpg', 'jpeg', 'png'])
    if uploaded_file:
        # Convert to base64
        bytes_data = uploaded_file.getvalue()
        base64_image = base64.b64encode(bytes_data).decode()
        success, message = update_profile(st.session_state.user_id, profile_photo=base64_image)
        if success:
            st.success("Profile photo updated!")
        else:
            st.error(message)

    # Display current photo if exists
    if user.profile_photo:
        st.image(base64.b64decode(user.profile_photo), width=150)

    # Personal Information
    st.subheader("Personal Information")
    with st.form("profile_form"):
        full_name = st.text_input("Full Name", value=user.full_name or "")
        email = st.text_input("Email", value=user.email or "")
        school = st.text_input("School", value=user.school or "")
        grade = st.text_input("Grade/Year", value=user.grade or "")

        if st.form_submit_button("Update Profile"):
            success, message = update_profile(
                st.session_state.user_id,
                full_name=full_name,
                email=email,
                school=school,
                grade=grade
            )
            if success:
                st.success("Profile updated successfully!")
            else:
                st.error(message)

    # Password Change
    st.subheader("Change Password")
    with st.form("password_form"):
        current_password = st.text_input("Current Password", type="password")
        new_password = st.text_input("New Password", type="password")
        confirm_password = st.text_input("Confirm New Password", type="password")

        if st.form_submit_button("Change Password"):
            if new_password != confirm_password:
                st.error("New passwords do not match")
            else:
                success, message = change_password(
                    st.session_state.user_id,
                    current_password,
                    new_password
                )
                if success:
                    st.success("Password updated successfully!")
                else:
                    st.error(message)

def render_auth_page():
    """Render login/signup page."""
    st.title("Mathematical Problem Solver")

    tab1, tab2 = st.tabs(["Login", "Sign Up"])

    with tab1:
        st.header("Login")
        login_username = st.text_input("Username", key="login_username")
        login_password = st.text_input("Password", type="password", key="login_password")

        if st.button("Login"):
            if login_user(login_username, login_password):
                st.success("Successfully logged in!")
                st.rerun()
            else:
                st.error("Invalid username or password")

    with tab2:
        st.header("Sign Up")
        signup_username = st.text_input("Username", key="signup_username")
        signup_password = st.text_input("Password", type="password", key="signup_password")
        confirm_password = st.text_input("Confirm Password", type="password")

        st.info("Password must be at least 8 characters long and contain at least one uppercase letter.")

        if st.button("Sign Up"):
            if signup_password != confirm_password:
                st.error("Passwords do not match")
            else:
                success, message = signup_user(signup_username, signup_password)
                if success:
                    st.success("Account created successfully!")
                    st.rerun()
                else:
                    st.error(message)

def main():
    # Initialize session state and load CSS
    initialize_session_state()
    load_css()

    if not is_logged_in():
        render_auth_page()
        return

    # Main app header with settings and logout buttons
    col1, col2, col3 = st.columns([6, 1, 1])
    with col1:
        st.title("Mathematical Problem Solver")
    with col2:
        if st.button("Settings"):
            st.session_state.show_settings = True
            st.rerun()
    with col3:
        if st.button("Logout"):
            logout_user()
            st.rerun()

    st.markdown(f"Welcome, {st.session_state.username}!")

    # Show settings or main app
    if st.session_state.get('show_settings', False):
        render_profile_settings()
        if st.button("Back to Calculator"):
            st.session_state.show_settings = False
            st.rerun()
    else:
        # Main calculator interface
        # Sidebar for history
        with st.sidebar:
            st.header("Solution History")
            history = load_user_history()
            if history:
                for idx, item in enumerate(history):
                    with st.expander(f"Problem {idx + 1}"):
                        st.write(f"Input: {item.equation}")
                        st.write(f"Solution: {item.solution}")
                        st.write(f"Date: {item.created_at.strftime('%Y-%m-%d %H:%M')}")

        # Input method selection
        input_method = st.radio(
            "Choose input method:",
            ["Type equation/expression", "Use camera", "Example problems"]
        )

        if input_method == "Type equation/expression":
            # Add math symbols
            render_math_symbols()

            # Equation input
            if 'equation' not in st.session_state:
                st.session_state.equation = ''

            equation = st.text_input(
                "Enter your equation or expression:",
                value=st.session_state.equation,
                help="""Examples:
                - Equation: x^2 + 2x + 1 = 0
                - Integration: ∫sin x
                - Derivative: d/dx(x^2)
                - Factorial: 5!
                - Laplace: ℒ(t^2)"""
            )
            st.session_state.equation = equation

        elif input_method == "Use camera":
            st.info("📸 Camera input feature is coming soon! For now, please type your equation or choose from examples.")
            equation = ""

        else:
            equation = st.selectbox(
                "Select an example:",
                [
                    "x^2 + 2x + 1 = 0",
                    "∫sin x",
                    "d/dx(x^3)",
                    "sin^2 x + cos^2 x",
                    "5!",
                    "2x + 3 = 7",
                    "e^x + 1 = 0",
                    "log(x) = 1"
                ]
            )

        if st.button("Solve"):
            if equation:
                try:
                    # Solve the equation or expression
                    solution = solve_equation(equation)
                    steps = generate_steps(equation)

                    # Display solution
                    st.markdown("### Solution")
                    st.write(solution)

                    # Display steps
                    st.markdown("### Step-by-step Solution")
                    for step in steps:
                        st.write(step)

                    # Plot the function if possible
                    try:
                        st.markdown("### Function Visualization")
                        fig = plot_function(equation)
                        st.plotly_chart(fig)
                    except Exception as plot_error:
                        st.info("Visualization not available for this type of expression.")

                    # Save to history
                    save_to_history(equation, solution)

                except Exception as e:
                    st.error(f"Error: {str(e)}")
            else:
                st.warning("Please enter an equation or expression")

if __name__ == "__main__":
    main()