fabianad commited on
Commit
a74b40e
·
verified ·
1 Parent(s): 8b4c122

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +327 -0
app.py ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import sympy as sp
3
+ from solver import solve_equation, generate_steps
4
+ from plotter import plot_function
5
+ from utils import load_css, initialize_session_state
6
+ from auth import (
7
+ login_user, signup_user, is_logged_in, logout_user,
8
+ update_profile, get_user_profile, change_password
9
+ )
10
+ from models import History, SessionLocal, init_db
11
+ import base64
12
+ from io import BytesIO
13
+
14
+ # Initialize database
15
+ init_db()
16
+
17
+ def save_to_history(equation: str, solution: str):
18
+ """Save equation and solution to user's history."""
19
+ if not is_logged_in():
20
+ return
21
+
22
+ db = SessionLocal()
23
+ try:
24
+ history = History(
25
+ user_id=st.session_state.user_id,
26
+ equation=equation,
27
+ solution=solution
28
+ )
29
+ db.add(history)
30
+ db.commit()
31
+ finally:
32
+ db.close()
33
+
34
+ def load_user_history():
35
+ """Load user's solution history."""
36
+ if not is_logged_in():
37
+ return []
38
+
39
+ db = SessionLocal()
40
+ try:
41
+ return db.query(History).filter(
42
+ History.user_id == st.session_state.user_id
43
+ ).order_by(History.created_at.desc()).all()
44
+ finally:
45
+ db.close()
46
+
47
+ def render_math_symbols():
48
+ """Render mathematical symbols for input."""
49
+ st.markdown("### Mathematical Operators")
50
+
51
+ cols = st.columns(8)
52
+ all_symbols = {
53
+ # Basic arithmetic
54
+ '×': '*',
55
+ '÷': '/',
56
+ '^': '^',
57
+ '=': '=',
58
+ '(': '(',
59
+ ')': ')',
60
+
61
+ # Functions and special operators
62
+ '√': '√',
63
+ '∫': '∫',
64
+ 'd/dx': 'd/dx',
65
+ '!': '!',
66
+ 'ℒ': 'L',
67
+ '∑': 'sum',
68
+ '∏': 'prod',
69
+ '|': '|',
70
+
71
+ # Constants
72
+ 'π': 'pi',
73
+ 'e': 'e',
74
+ 'i': 'i',
75
+ '∞': 'oo',
76
+
77
+ # Trigonometric
78
+ 'sin': 'sin(',
79
+ 'cos': 'cos(',
80
+ 'tan': 'tan(',
81
+ 'csc': 'csc(',
82
+ 'sec': 'sec(',
83
+ 'cot': 'cot(',
84
+
85
+ # Inverse trigonometric
86
+ 'sin⁻¹': 'sin⁻¹(',
87
+ 'cos⁻¹': 'cos⁻¹(',
88
+ 'tan⁻¹': 'tan⁻¹(',
89
+
90
+ # Other functions
91
+ 'ln': 'ln(',
92
+ 'log': 'log(',
93
+ 'e^': 'e^',
94
+ '|x|': 'abs(',
95
+ }
96
+
97
+ for i, (label, symbol) in enumerate(all_symbols.items()):
98
+ col_idx = i % 8
99
+ if cols[col_idx].button(label, key=f"btn_{label}", help=f"Insert {label}"):
100
+ if 'equation' not in st.session_state:
101
+ st.session_state.equation = ''
102
+ st.session_state.equation += symbol
103
+
104
+ def render_profile_settings():
105
+ """Render user profile settings page."""
106
+ st.title("Profile Settings")
107
+
108
+ user = get_user_profile(st.session_state.user_id)
109
+
110
+ # Profile photo upload
111
+ st.subheader("Profile Photo")
112
+ uploaded_file = st.file_uploader("Choose a profile photo", type=['jpg', 'jpeg', 'png'])
113
+ if uploaded_file:
114
+ # Convert to base64
115
+ bytes_data = uploaded_file.getvalue()
116
+ base64_image = base64.b64encode(bytes_data).decode()
117
+ success, message = update_profile(st.session_state.user_id, profile_photo=base64_image)
118
+ if success:
119
+ st.success("Profile photo updated!")
120
+ else:
121
+ st.error(message)
122
+
123
+ # Display current photo if exists
124
+ if user.profile_photo:
125
+ st.image(base64.b64decode(user.profile_photo), width=150)
126
+
127
+ # Personal Information
128
+ st.subheader("Personal Information")
129
+ with st.form("profile_form"):
130
+ full_name = st.text_input("Full Name", value=user.full_name or "")
131
+ email = st.text_input("Email", value=user.email or "")
132
+ school = st.text_input("School", value=user.school or "")
133
+ grade = st.text_input("Grade/Year", value=user.grade or "")
134
+
135
+ if st.form_submit_button("Update Profile"):
136
+ success, message = update_profile(
137
+ st.session_state.user_id,
138
+ full_name=full_name,
139
+ email=email,
140
+ school=school,
141
+ grade=grade
142
+ )
143
+ if success:
144
+ st.success("Profile updated successfully!")
145
+ else:
146
+ st.error(message)
147
+
148
+ # Password Change
149
+ st.subheader("Change Password")
150
+ with st.form("password_form"):
151
+ current_password = st.text_input("Current Password", type="password")
152
+ new_password = st.text_input("New Password", type="password")
153
+ confirm_password = st.text_input("Confirm New Password", type="password")
154
+
155
+ if st.form_submit_button("Change Password"):
156
+ if new_password != confirm_password:
157
+ st.error("New passwords do not match")
158
+ else:
159
+ success, message = change_password(
160
+ st.session_state.user_id,
161
+ current_password,
162
+ new_password
163
+ )
164
+ if success:
165
+ st.success("Password updated successfully!")
166
+ else:
167
+ st.error(message)
168
+
169
+ def render_auth_page():
170
+ """Render login/signup page."""
171
+ st.title("Mathematical Problem Solver")
172
+
173
+ tab1, tab2 = st.tabs(["Login", "Sign Up"])
174
+
175
+ with tab1:
176
+ st.header("Login")
177
+ login_username = st.text_input("Username", key="login_username")
178
+ login_password = st.text_input("Password", type="password", key="login_password")
179
+
180
+ if st.button("Login"):
181
+ if login_user(login_username, login_password):
182
+ st.success("Successfully logged in!")
183
+ st.rerun()
184
+ else:
185
+ st.error("Invalid username or password")
186
+
187
+ with tab2:
188
+ st.header("Sign Up")
189
+ signup_username = st.text_input("Username", key="signup_username")
190
+ signup_password = st.text_input("Password", type="password", key="signup_password")
191
+ confirm_password = st.text_input("Confirm Password", type="password")
192
+
193
+ st.info("Password must be at least 8 characters long and contain at least one uppercase letter.")
194
+
195
+ if st.button("Sign Up"):
196
+ if signup_password != confirm_password:
197
+ st.error("Passwords do not match")
198
+ else:
199
+ success, message = signup_user(signup_username, signup_password)
200
+ if success:
201
+ st.success("Account created successfully!")
202
+ st.rerun()
203
+ else:
204
+ st.error(message)
205
+
206
+ def main():
207
+ # Initialize session state and load CSS
208
+ initialize_session_state()
209
+ load_css()
210
+
211
+ if not is_logged_in():
212
+ render_auth_page()
213
+ return
214
+
215
+ # Main app header with settings and logout buttons
216
+ col1, col2, col3 = st.columns([6, 1, 1])
217
+ with col1:
218
+ st.title("Mathematical Problem Solver")
219
+ with col2:
220
+ if st.button("Settings"):
221
+ st.session_state.show_settings = True
222
+ st.rerun()
223
+ with col3:
224
+ if st.button("Logout"):
225
+ logout_user()
226
+ st.rerun()
227
+
228
+ st.markdown(f"Welcome, {st.session_state.username}!")
229
+
230
+ # Show settings or main app
231
+ if st.session_state.get('show_settings', False):
232
+ render_profile_settings()
233
+ if st.button("Back to Calculator"):
234
+ st.session_state.show_settings = False
235
+ st.rerun()
236
+ else:
237
+ # Main calculator interface
238
+ # Sidebar for history
239
+ with st.sidebar:
240
+ st.header("Solution History")
241
+ history = load_user_history()
242
+ if history:
243
+ for idx, item in enumerate(history):
244
+ with st.expander(f"Problem {idx + 1}"):
245
+ st.write(f"Input: {item.equation}")
246
+ st.write(f"Solution: {item.solution}")
247
+ st.write(f"Date: {item.created_at.strftime('%Y-%m-%d %H:%M')}")
248
+
249
+ # Input method selection
250
+ input_method = st.radio(
251
+ "Choose input method:",
252
+ ["Type equation/expression", "Use camera", "Example problems"]
253
+ )
254
+
255
+ if input_method == "Type equation/expression":
256
+ # Add math symbols
257
+ render_math_symbols()
258
+
259
+ # Equation input
260
+ if 'equation' not in st.session_state:
261
+ st.session_state.equation = ''
262
+
263
+ equation = st.text_input(
264
+ "Enter your equation or expression:",
265
+ value=st.session_state.equation,
266
+ help="""Examples:
267
+ - Equation: x^2 + 2x + 1 = 0
268
+ - Integration: ∫sin x
269
+ - Derivative: d/dx(x^2)
270
+ - Factorial: 5!
271
+ - Laplace: ℒ(t^2)"""
272
+ )
273
+ st.session_state.equation = equation
274
+
275
+ elif input_method == "Use camera":
276
+ st.info("📸 Camera input feature is coming soon! For now, please type your equation or choose from examples.")
277
+ equation = ""
278
+
279
+ else:
280
+ equation = st.selectbox(
281
+ "Select an example:",
282
+ [
283
+ "x^2 + 2x + 1 = 0",
284
+ "∫sin x",
285
+ "d/dx(x^3)",
286
+ "sin^2 x + cos^2 x",
287
+ "5!",
288
+ "2x + 3 = 7",
289
+ "e^x + 1 = 0",
290
+ "log(x) = 1"
291
+ ]
292
+ )
293
+
294
+ if st.button("Solve"):
295
+ if equation:
296
+ try:
297
+ # Solve the equation or expression
298
+ solution = solve_equation(equation)
299
+ steps = generate_steps(equation)
300
+
301
+ # Display solution
302
+ st.markdown("### Solution")
303
+ st.write(solution)
304
+
305
+ # Display steps
306
+ st.markdown("### Step-by-step Solution")
307
+ for step in steps:
308
+ st.write(step)
309
+
310
+ # Plot the function if possible
311
+ try:
312
+ st.markdown("### Function Visualization")
313
+ fig = plot_function(equation)
314
+ st.plotly_chart(fig)
315
+ except Exception as plot_error:
316
+ st.info("Visualization not available for this type of expression.")
317
+
318
+ # Save to history
319
+ save_to_history(equation, solution)
320
+
321
+ except Exception as e:
322
+ st.error(f"Error: {str(e)}")
323
+ else:
324
+ st.warning("Please enter an equation or expression")
325
+
326
+ if __name__ == "__main__":
327
+ main()