namngo commited on
Commit
26bca26
·
verified ·
1 Parent(s): 0e6e452

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +149 -303
app.py CHANGED
@@ -15,23 +15,23 @@ st.set_page_config(page_title="Dự đoán tốt nghiệp đúng hạn", page_ic
15
 
16
  # ===== Custom CSS =====
17
  st.markdown("""
18
-     <style>
19
-     html, body, [class*="css"]  {
20
-         font-family: 'Poppins', sans-serif;
21
-     }
22
-     .block-container {
23
-         padding: 2rem 2rem 2rem 2rem;
24
-     }
25
-     .stButton button {
26
-         background: linear-gradient(90deg, #4F8BF9 0%, #8E2DE2 100%);
27
-         border: none;
28
-         padding: 0.75em 1.5em;
29
-         border-radius: 8px;
30
-         color: white;
31
-         font-size: 18px;
32
-         font-weight: bold;
33
-     }
34
-     </style>
35
  """, unsafe_allow_html=True)
36
 
37
  # ===== GSheet integration =====
@@ -44,35 +44,35 @@ def get_gsheet_client():
44
 
45
  # ===== Save to Google Sheets =====
46
  def save_to_gsheet(name, student_id, major, prediction, semester_data, sheet_name="Trang tính1"):
47
-     # Get the current date and time
48
-     now = datetime.now()
49
-     current_time = now.strftime("%Y-%m-%d %H:%M:%S")
50
-     
51
-     # Ensure prediction is in the expected format (0 or 1)
52
-     if isinstance(prediction, np.ndarray):
53
-         prediction = int(prediction[0])  # Convert to int if it's ndarray
54
-     
55
-     elif isinstance(prediction, np.int64):
56
-         prediction = int(prediction)  # Convert np.int64 to int
57
-     
58
-     # Flatten semester data to individual columns for each semester
59
-     semester_data_flat = [str(val) for val in semester_data]  # Convert all semester data values to strings
60
-     
61
-     # Create a data row to insert into the sheet
62
-     data_row = [name, student_id, major, prediction, current_time] + semester_data_flat
63
-
64
-     # Connect to Google Sheets
65
-     client = get_gsheet_client()
66
-
67
-     # Use the Spreadsheet ID (replace with your actual ID)
68
-     sheet_id = "1i7bDNvLVLXN93_e-FN0JLzpg1jb64Z_aEuyPjIfwbdQ"  # Use your actual ID here
69
-     sheet = client.open_by_key(sheet_id).worksheet(sheet_name)
70
-
71
-     # Get all values from the sheet to check if the first row is empty (i.e., headers not created yet)
72
-     all_values = sheet.get_all_values()
73
 
74
  # Define headers based on the model type for accurate sheet saving
75
- if sheet_name == "Trang tính1": # Full features model
76
  headers = ["Họ và tên", "MSV", "Khoa", "Dự báo", "Thời gian"] + [
77
  f"Số môn không thi - HK{i+1}" for i in range(6)] + [
78
  f"Số tín chỉ không thi - HK{i+1}" for i in range(6)] + [
@@ -85,30 +85,18 @@ def save_to_gsheet(name, student_id, major, prediction, semester_data, sheet_nam
85
  f"GPA - HK{i+1}" for i in range(6)] + [
86
  f"Xếp loại - HK{i+1}" for i in range(6)]
87
 
88
- elif sheet_name == "Trang tính2": # Important features model
89
- headers = ["Họ và tên", "MSV", "Khoa", "Dự báo", "Thời gian"] + [
90
  f"Số tín chỉ đạt - HK{i+1}" for i in range(6)] + [
91
  f"Số tín chỉ nợ - HK{i+1}" for i in range(6)] + [
92
  f"Điểm trung bình - HK{i+1}" for i in range(6)]
93
 
94
  # If the sheet is empty or if headers are missing, insert headers
95
-     if not all_values or len(all_values[0]) != len(headers):  # Ensure number of columns matches expected headers
96
-         sheet.append_row(headers)  # Create headers if missing
97
-     
98
-     # Append data to the sheet
99
-     sheet.append_row(data_row)
100
-
101
-
102
- # ===== List all sheet names =====
103
- # def list_sheet_names(sheet_id):
104
- #     client = get_gsheet_client()
105
- #     sheet = client.open_by_key(sheet_id)
106
-     
107
- #     # List all sheet names
108
- #     sheet_names = [worksheet.title for worksheet in sheet.worksheets()]
109
- #     return sheet_names
110
-
111
-
112
 
113
  # ===== HEADER =====
114
  st.markdown("<h1 style='text-align: center; color: #003366;'>🎓 DỰ ĐOÁN KHẢ NĂNG TỐT NGHIỆP ĐÚNG HẠN</h1>", unsafe_allow_html=True)
@@ -123,135 +111,110 @@ st.subheader("🔢 Chọn ví dụ mẫu hoặc nhập thông tin cá nhân")
123
 
124
  sample_option = st.selectbox("📝 Chọn ví dụ:", ["Không ví dụ", "Dùng ví dụ mẫu ngành Công nghệ thông tin", "Dùng ví dụ mẫu ngành Kinh tế"])
125
 
126
- # ===== Ví dụ mẫu cho mô hình "Dùng toàn bộ dữ liệu" =====
127
  sample_cntt_example_full = {
128
-     "name": "Nguyễn Văn A",
129
-     "student_id": "10117367",
130
-     "major": "Công nghệ thông tin",
131
-     "semester_data": [
132
-         0, 0, 0, 0, 17, 7, 7, 8.73, 0,
133
-         0, 0, 0, 0, 17, 7, 7, 8.19, 0,
134
-         0, 0, 0, 0, 17, 7, 7, 7.90, 0,
135
-         0, 0, 0, 0, 17, 7, 7, 8.19, 0,
136
-         0, 0, 0, 0, 19, 7, 6, 8.18, 0,
137
-         0, 0, 5, 2, 19, 7, 5, 7.10, 1
138
-     ]
139
  }
140
 
141
- # ===== Ví dụ mẫu cho mô hình "Dùng mô hình đơn giản" =====
142
- # ===== Ví dụ cho mô hình "Dùng mô hình đơn giản" cho Kinh tế =====
143
  sample_kinhte_example_simple = {
144
-     "name": "Trần Thị B",
145
-     "student_id": "11418092",
146
-     "major": "Kinh tế",
147
-     "semester_data": [
148
-         17, 7, 7.64,  # Học kỳ 1: Số tín chỉ đạt, Số tín chỉ nợ, GPA
149
-         17, 7, 7.19,  # Học kỳ 2: Số tín chỉ đạt, Số tín chỉ nợ, GPA
150
-         17, 7, 6.94,  # Học kỳ 3: Số tín chỉ đạt, Số tín chỉ nợ, GPA
151
-         17, 7, 7.19,  # Học kỳ 4: Số tín chỉ đạt, Số tín chỉ nợ, GPA
152
-         19, 7, 7.65,  # Học kỳ 5: Số tín chỉ đạt, Số tín chỉ nợ, GPA
153
-         19, 7, 7.49   # Học kỳ 6: Số tín chỉ đạt, Số tín chỉ nợ, GPA
154
-     ]
155
  }
156
 
157
 
158
- # ===== Ví dụ cho mô hình "Dùng mô hình đơn giản" cho CNTT =====
159
  # ===== Ví dụ cho mô hình "Dùng mô hình đơn giản" cho CNTT =====
160
  sample_cntt_example_simple = {
161
-     "name": "Nguyễn Văn B",
162
-     "student_id": "10117368",
163
-     "major": "Công nghệ thông tin",
164
-     "semester_data": [
165
-         15, 8, 7.50,  # Học kỳ 1: Số tín chỉ đạt, Số tín chỉ nợ, GPA
166
-         17, 7, 8.10,  # Học kỳ 2: Số tín chỉ đạt, Số tín chỉ nợ, GPA
167
-         18, 7, 7.90,  # Học kỳ 3: Số tín chỉ đạt, Số tín chỉ nợ, GPA
168
-         17, 7, 7.80,  # Học kỳ 4: Số tín chỉ đạt, Số tín chỉ nợ, GPA
169
-         19, 8, 8.30,  # Học kỳ 5: Số tín chỉ đạt, Số tín chỉ nợ, GPA
170
-         19, 7, 7.20   # Học kỳ 6: Số tín chỉ đạt, Số tín chỉ nợ, GPA
171
-     ]
172
  }
173
 
174
  # ===== Ví dụ cho mô hình "Dùng mô hình đơn giản" cho Kinh tế =====
175
  sample_kinhte_example_full = {
176
-     "name": "Trần Thị C",
177
-     "student_id": "11418093",
178
-     "major": "Kinh tế",
179
-     "semester_data": [
180
-         0, 0, 0, 0, 16, 6, 6, 7.00, 1,
181
-         0, 0, 0, 0, 18, 7, 7, 8.20, 1,
182
-         0, 0, 0, 0, 17, 7, 7, 7.80, 1,
183
-         0, 0, 0, 0, 17, 7, 6, 7.90, 1,
184
-         0, 0, 0, 0, 19, 8, 5, 8.10, 0,
185
-         0, 0, 8, 2, 19, 7, 6, 7.30, 1
186
-     ]
187
  }
188
 
189
  # ===== Thông tin cá nhân =====
190
  if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin":
191
-     # Check model type to load appropriate example data
192
  if model_type == "Dùng toàn bộ đặc trưng":
193
  sample_data_personal = sample_cntt_example_full
194
  else: # Dùng đặc trưng quan trọng
195
  sample_data_personal = sample_cntt_example_simple
196
  name = st.text_input("👤 Họ và tên", value=sample_data_personal["name"])
197
-     student_id = st.text_input("🎓 Mã sinh viên", value=sample_data_personal["student_id"])
198
-     major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"], index=0)
199
  elif sample_option == "Dùng ví dụ mẫu ngành Kinh tế":
200
  # Check model type to load appropriate example data
201
  if model_type == "Dùng toàn bộ đặc trưng":
202
  sample_data_personal = sample_kinhte_example_full
203
  else: # Dùng đặc trưng quan trọng
204
  sample_data_personal = sample_kinhte_example_simple
205
-     name = st.text_input("👤 Họ và tên", value=sample_data_personal["name"])
206
-     student_id = st.text_input("🎓 Mã sinh viên", value=sample_data_personal["student_id"])
207
-     major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"], index=1)
208
  else:
209
-     name = st.text_input("👤 Họ và tên")
210
-     student_id = st.text_input("🎓 Mã sinh viên")
211
-     major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"])
212
-
213
 
214
  st.write("---")
215
 
216
  # ===== Nhập thông tin học kỳ =====
217
  def input_semester(semester_label, default_values=None):
218
-     with st.expander(f"📖 {semester_label}", expanded=True):
219
-         col1, col2 = st.columns(2)
220
-         with col1:
221
-             somon0thi = st.number_input("Số môn không thi", 0, value=default_values[0] if default_values else 0, key=f"sm0_{semester_label}")
222
-             sotc0thi = st.number_input("Số tín chỉ không thi", 0, value=default_values[1] if default_values else 0, key=f"tc0_{semester_label}")
223
-             sotcno = st.number_input("Số tín chỉ nợ", 0, value=default_values[2] if default_values else 0, key=f"tcno_{semester_label}")
224
-             mhno = st.number_input("Số môn không đạt", 0, value=default_values[3] if default_values else 0, key=f"mhno_{semester_label}")
225
-             try:
226
-                 default_tc_qua = default_values[4] - default_values[2] if default_values and len(default_values) >= 5 else 0 # This calculation seems incorrect for "Số tín chỉ qua môn" if default_values[4] is Total Credit
227
-             except:
228
-                 default_tc_qua = 0
229
- # Correcting default value logic for "Số tín chỉ qua môn" based on sample data structure
230
- # If default_values has 9 elements (full model data), default_tc_qua is at index 4
231
- if default_values and len(default_values) == 9:
232
- default_tc_qua_input = default_values[4]
233
- else:
234
- default_tc_qua_input = 0 # Or some default
235
-             sotc_qua = st.number_input("Số tín chỉ qua môn", 0, value=default_tc_qua_input, key=f"tcqua_{semester_label}")
236
-         with col2:
237
-             TCHK = st.number_input("Tổng tín chỉ học kỳ", 0, value=default_values[4] if default_values else 0, key=f"tchk_{semester_label}")
238
-             smhk = st.number_input("Số môn học kỳ", 0, value=default_values[5] if default_values else 0, key=f"smhk_{semester_label}")
239
-             mhpass = st.number_input("Số môn đạt", 0, value=default_values[6] if default_values else 0, key=f"mhpass_{semester_label}")
240
-             TBCHK = st.number_input("GPA", 0.0, 10.0, value=default_values[7] if default_values else 0.0, step=0.01, key=f"gpa_{semester_label}")
241
-             xep_loai_selected = st.selectbox("Xếp loại", list(range(7)), index=default_values[8] if default_values else 0, key=f"xeploai_{semester_label}")
242
-     return [somon0thi, sotc0thi, sotcno, mhno, TCHK, smhk, mhpass, TBCHK, xep_loai_selected, sotc_qua]
243
-
244
- def input_important_features(semester_label, default_values=None):
245
-     with st.expander(f"📘 {semester_label}", expanded=True):
246
-         col1, col2, col3 = st.columns(3) # Use 3 columns for important features layout
247
-         with col1:
248
-             # Use consistent keys for input fields
249
-             sotc_qua = st.number_input("Số tín chỉ đạt", 0, value=default_values[0] if default_values and len(default_values) > 0 else 0, key=f"tcqua_imp_{semester_label}")
250
-         with col2:
251
-             sotcno = st.number_input("Số tín chỉ nợ", 0, value=default_values[1] if default_values and len(default_values) > 1 else 0, key=f"tcno_imp_{semester_label}")
252
-         with col3:
253
-             TBCHK = st.number_input("Điểm trung bình", 0.0, 10.0, value=default_values[2] if default_values and len(default_values) > 2 else 0.0, step=0.01, key=f"gpa_imp_{semester_label}")
254
-     return [sotc_qua, sotcno, TBCHK]
255
 
256
  # ===== Giao diện theo mô hình =====
257
  data = []
@@ -259,163 +222,46 @@ semesters = ["HỌC KỲ I", "HỌC KỲ II", "HỌC KỲ III", "HỌC KỲ IV",
259
 
260
  # Mô hình 1: "Dùng toàn bộ dữ liệu"
261
  if model_type == "Dùng toàn bộ đặc trưng":
262
-     st.subheader("🔢 Nhập thông tin học kỳ chi tiết")
263
-     for idx, sem in enumerate(semesters):
264
-         example_data = sample_cntt_example_full if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin" else sample_kinhte_example_full if sample_option == "Dùng ví dụ mẫu ngành Kinh tế" else None
265
-         # Full model data has 9 features per semester + 1 extra (sotc_qua, which was calculated) = 10 features.
266
- # Update: based on the data structure, there are 9 features per semester in the full model example.
267
- # The input_semester function returns 10 values. Let's check the save_to_gsheet function's headers for full model.
268
- # Headers for full model have 9 semester specific columns per semester.
269
- # Let's correct input_semester to return 9 values matching the headers/example data.
270
- # The example data has 9 values per semester for the full model.
271
- # Let's fix the input_semester function to match the example data and headers (9 features).
272
- # The example data has [0, 0, 0, 0, 17, 7, 7, 8.73, 0] -> 9 values.
273
- # The input_semester returns [somon0thi, sotc0thi, sotcno, mhno, TCHK, smhk, mhpass, TBCHK, xep_loai_selected, sotc_qua] -> 10 values.
274
- # The save_to_gsheet headers for full model list 9 columns per semester.
275
- # Let's align input_semester to return the 9 values that correspond to the headers.
276
- # Headers: Số môn không thi, Số tín chỉ không thi, Số tín chỉ nợ, Số môn không đạt, Số tín chỉ qua môn, Tổng tín chỉ học kỳ, Số môn học kỳ, Số môn đạt, GPA, Xếp loại
277
- # This is 10 headers per semester. The example data has 9. Let's fix the example data structure to match headers or vice versa.
278
- # Assuming headers are correct: Número môn không thi, Số tín chỉ không thi, Số tín chỉ nợ, Số môn không đạt, Số tín chỉ qua môn, Tổng tín chỉ học kỳ, Số môn học kỳ, Số môn đạt, GPA, Xếp loại (10 features)
279
- # Let's update the example data for the full model to include all 10 features if possible or remove headers that don't match the example data.
280
- # Given the original code's save_to_gsheet headers for the full model list 10 items per semester type, and the example data for full model has 9 items per semester type, there's a mismatch.
281
- # Let's assume the `input_semester` function's return values are correct based on the intended model features, and the `sample_cntt_example_full` and `sample_kinhte_example_full` are slightly off or need adjustment to match the 10 inputs.
282
- # The `input_semester` returns: somon0thi, sotc0thi, sotcno, mhno, TCHK, smhk, mhpass, TBCHK, xep_loai_selected, sotc_qua. This is 10 values.
283
- # The `save_to_gsheet` headers for 'Trang tính1' list 10 headers per semester type. This matches.
284
- # The `sample_cntt_example_full` and `sample_kinhte_example_full` have 9 values per semester. This is where the discrepancy is.
285
- # To make the examples work correctly with the full model inputs, the example data structure should match the 10 features collected by `input_semester`.
286
- # The missing feature in the example data seems to be `sotc_qua`.
287
- # Let's adjust the example data to include a value for `sotc_qua` for each semester, or adjust the `input_semester` default value logic.
288
- # A simpler fix for now is to adjust the `input_semester` default value logic to handle the case where example data might be shorter.
289
- # The `default_tc_qua_input` line within `input_semester` was calculating it, let's remove that and rely solely on the example data if available.
290
- # And if example data for `sotc_qua` is missing, default to 0.
291
-
292
- # Corrected input_semester default value handling:
293
- def input_semester_corrected(semester_label, default_values=None):
294
- with st.expander(f"📖 {semester_label}", expanded=True):
295
- col1, col2 = st.columns(2)
296
- with col1:
297
- somon0thi = st.number_input("Số môn không thi", 0, value=default_values[0] if default_values and len(default_values) > 0 else 0, key=f"sm0_{semester_label}")
298
- sotc0thi = st.number_input("Số tín chỉ không thi", 0, value=default_values[1] if default_values and len(default_values) > 1 else 0, key=f"tc0_{semester_label}")
299
- sotcno = st.number_input("Số tín chỉ nợ", 0, value=default_values[2] if default_values and len(default_values) > 2 else 0, key=f"tcno_{semester_label}")
300
- mhno = st.number_input("Số môn không đạt", 0, value=default_values[3] if default_values and len(default_values) > 3 else 0, key=f"mhno_{semester_label}")
301
- # Assuming sotc_qua is the 5th value in the example data if 9 values exist
302
- sotc_qua_default = default_values[4] if default_values and len(default_values) > 4 else 0
303
- sotc_qua = st.number_input("Số tín chỉ qua môn", 0, value=sotc_qua_default, key=f"tcqua_{semester_label}")
304
- with col2:
305
- TCHK = st.number_input("Tổng tín chỉ học kỳ", 0, value=default_values[5] if default_values and len(default_values) > 5 else 0, key=f"tchk_{semester_label}")
306
- smhk = st.number_input("Số môn học kỳ", 0, value=default_values[6] if default_values and len(default_values) > 6 else 0, key=f"smhk_{semester_label}")
307
- mhpass = st.number_input("Số môn đạt", 0, value=default_values[7] if default_values and len(default_values) > 7 else 0, key=f"mhpass_{semester_label}")
308
- TBCHK = st.number_input("GPA", 0.0, 10.0, value=default_values[8] if default_values and len(default_values) > 8 else 0.0, step=0.01, key=f"gpa_{semester_label}")
309
- xep_loai_selected = st.selectbox("Xếp loại", list(range(7)), index=default_values[9] if default_values and len(default_values) > 9 else 0, key=f"xeploai_{semester_label}") # Assuming Xếp loại is the 10th value
310
- return [somon0thi, sotc0thi, sotcno, mhno, sotc_qua, TCHK, smhk, mhpass, TBCHK, xep_loai_selected] # Return 10 values
311
-
312
- # Let's update the example data structure to have 10 values per semester for consistency
313
- # Based on the headers, the order should be: Số môn không thi, Số tín chỉ không thi, Số tín chỉ nợ, Số môn không đạt, Số tín chỉ qua môn, Tổng tín chỉ học kỳ, Số môn học kỳ, Số môn đạt, GPA, Xếp loại
314
- # The original example data was [somon0thi, sotc0thi, sotcno, mhno, TCHK, smhk, mhpass, TBCHK, xep_loai_selected] -> 9 values
315
- # It seems "Số tín chỉ qua môn" was missing or intended to be calculated.
316
- # Let's assume "Số tín chỉ qua môn" is implicitly TCHK - sotcno.
317
- # However, the headers list "Số tín chỉ qua môn" as a separate column.
318
- # Let's assume the headers are correct and the example data needs to match the headers.
319
- # Let's restructure example data to have 10 values, adding a plausible value for "Số tín chỉ qua môn" (TCHK - sotcno).
320
-
321
- sample_cntt_example_full = {
322
- "name": "Nguyễn Văn A",
323
- "student_id": "10117367",
324
- "major": "Công nghệ thông tin",
325
- "semester_data": [
326
- # HK1: sm0, tc0, tcno, mhno, tc_qua (calculated: TCHK-tcno), TCHK, smhk, mhpass, GPA, xeploai
327
- 0, 0, 0, 0, 17-0, 17, 7, 7, 8.73, 0,
328
- # HK2:
329
- 0, 0, 0, 0, 17-0, 17, 7, 7, 8.19, 0,
330
- # HK3:
331
- 0, 0, 0, 0, 17-0, 17, 7, 7, 7.90, 0,
332
- # HK4:
333
- 0, 0, 0, 0, 17-0, 17, 7, 7, 8.19, 0,
334
- # HK5:
335
- 0, 0, 0, 0, 19-0, 19, 7, 6, 8.18, 0,
336
- # HK6: tcno=5, mhno=2, TCHK=19, mhpass=6, xeploai=1. Assuming tc_qua = TCHK - tcno = 19-5 = 14
337
- 0, 0, 5, 2, 19-5, 19, 7, 6, 7.10, 1
338
- ]
339
- }
340
-
341
- sample_kinhte_example_full = {
342
- "name": "Trần Thị C",
343
- "student_id": "11418093",
344
- "major": "Kinh tế",
345
- "semester_data": [
346
- # HK1:
347
- 0, 0, 0, 0, 16-0, 16, 6, 6, 7.00, 1,
348
- # HK2:
349
- 0, 0, 0, 0, 18-0, 18, 7, 7, 8.20, 1,
350
- # HK3:
351
- 0, 0, 0, 0, 17-0, 17, 7, 7, 7.80, 1,
352
- # HK4:
353
- 0, 0, 0, 0, 17-0, 17, 7, 6, 7.90, 1,
354
- # HK5:
355
- 0, 0, 0, 0, 19-0, 19, 8, 5, 8.10, 0,
356
- # HK6: tcno=8, mhno=2, TCHK=19, mhpass=6, xeploai=1. Assuming tc_qua = TCHK - tcno = 19-8 = 11
357
- 0, 0, 8, 2, 19-8, 19, 7, 6, 7.30, 1
358
- ]
359
- }
360
- # Now the example data for the full model should match the 10 inputs per semester.
361
-
362
  example_data = sample_cntt_example_full if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin" else sample_kinhte_example_full if sample_option == "Dùng ví dụ mẫu ngành Kinh tế" else None
363
-         default_values = example_data["semester_data"][idx*10:(idx+1)*10] if example_data else None # Slice 10 values
364
-         data += input_semester_corrected(sem, default_values) # Use the corrected function
365
-     nganh = 0 if major == "Công nghệ thông tin" else 1
366
-     final_features = np.array(data + [nganh]).reshape(1, -1)
367
-
368
 
369
  # Mô hình 2: "Dùng đặc trưng quan trọng"
370
  else: # model_type == "Dùng đặc trưng quan trọng"
371
-     st.subheader("✨ Nhập thông tin rút gọn")
372
-     
373
-     # Allow selecting an example
374
-     for idx, sem in enumerate(semesters):
375
-         example_data = sample_cntt_example_simple if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin" else sample_kinhte_example_simple if sample_option == "Dùng ví dụ mẫu ngành Kinh tế" else None
376
-         # Slice 3 values per semester for the simple model example data
377
-         default_values = example_data["semester_data"][idx*3:(idx+1)*3] if example_data else None 
378
-
379
-         # Use expander to group each semester's fields
380
  with st.expander(f"📘 {sem}", expanded=True):
381
- # Use 3 columns to align with the image layout for all semesters
382
  col1, col2, col3 = st.columns(3)
383
  with col1:
384
- # Use consistent keys for input fields
385
- sotc_qua = st.number_input("Số tín chỉ đạt", 0, value=default_values[0] if default_values and len(default_values) > 0 else 0, key=f"tcqua_imp_{sem}")
386
  with col2:
387
- sotcno = st.number_input("Số tín chỉ nợ", 0, value=default_values[1] if default_values and len(default_values) > 1 else 0, key=f"tcno_imp_{sem}")
388
  with col3:
389
- # Adjusted label to match the image: "Điểm trung bình hệ 10"
390
- TBCHK = st.number_input("Điểm trung bình hệ 10", 0.0, 10.0, value=default_values[2] if default_values and len(default_values) > 2 else 0.0, step=0.01, key=f"gpa_imp_{sem}")
391
-
392
-         # Collect semester data (3 values per semester)
393
-         data += [sotc_qua, sotcno, TBCHK]  
394
-     
395
-     final_features = np.array(data).reshape(1, -1) # Should be 6 semesters * 3 features = 18 features
396
 
397
  # ===== Predict =====
398
  if st.button("🎯 DỰ BÁO"):
399
-     if model_type == "Dùng toàn bộ đặc trưng":
400
-         prediction = model_full.predict(final_features)
401
-         sheet_name = "Trang tính1"  # For full data model, save to Trang tính1
402
-
403
-     else: # model_type == "Dùng đặc trưng quan trọng"
404
-         prediction = model_important.predict(final_features)
405
-         sheet_name = "Trang tính2"  # For important data model, save to Trang tính2
406
-
407
 
408
-     if prediction[0] == 1:
409
-         st.success(f"🎉 Chúc mừng bạn {name} - {major}! Bạn có khả năng tốt nghiệp đúng hạn!")
410
-         st.balloons()
411
-     else:
412
-         st.error(f"⚠️ Bạn {name} - {major} cần cố gắng hơn! Có nguy cơ trễ hạn.")
413
-         st.snow()
414
 
415
-     # # Debugging: List all sheet names
416
-     # sheet_id = "1i7bDNvLVLXN93_e-FN0JLzpg1jb64Z_aEuyPjIfwbdQ"  # Use your actual Spreadsheet ID
417
-     # sheet_names = list_sheet_names(sheet_id)
418
-     # st.write("Available sheet names:", sheet_names)
 
 
419
 
420
-     # Ghi log lên Google Sheets
421
-     save_to_gsheet(name, student_id, major, prediction, data,sheet_name)  # Pass data to save function
 
15
 
16
  # ===== Custom CSS =====
17
  st.markdown("""
18
+ <style>
19
+ html, body, [class*="css"] {
20
+ font-family: 'Poppins', sans-serif;
21
+ }
22
+ .block-container {
23
+ padding: 2rem 2rem 2rem 2rem;
24
+ }
25
+ .stButton button {
26
+ background: linear-gradient(90deg, #4F8BF9 0%, #8E2DE2 100%);
27
+ border: none;
28
+ padding: 0.75em 1.5em;
29
+ border-radius: 8px;
30
+ color: white;
31
+ font-size: 18px;
32
+ font-weight: bold;
33
+ }
34
+ </style>
35
  """, unsafe_allow_html=True)
36
 
37
  # ===== GSheet integration =====
 
44
 
45
  # ===== Save to Google Sheets =====
46
  def save_to_gsheet(name, student_id, major, prediction, semester_data, sheet_name="Trang tính1"):
47
+ # Get the current date and time
48
+ now = datetime.now()
49
+ current_time = now.strftime("%Y-%m-%d %H:%M:%S")
50
+
51
+ # Ensure prediction is in the expected format (0 or 1)
52
+ if isinstance(prediction, np.ndarray):
53
+ prediction = int(prediction[0]) # Convert to int if it's ndarray
54
+
55
+ elif isinstance(prediction, np.int64):
56
+ prediction = int(prediction) # Convert np.int64 to int
57
+
58
+ # Flatten semester data to individual columns for each semester
59
+ semester_data_flat = [str(val) for val in semester_data] # Convert all semester data values to strings
60
+
61
+ # Create a data row to insert into the sheet
62
+ data_row = [name, student_id, major, prediction, current_time] + semester_data_flat
63
+
64
+ # Connect to Google Sheets
65
+ client = get_gsheet_client()
66
+
67
+ # Use the Spreadsheet ID (replace with your actual ID)
68
+ sheet_id = "1i7bDNvLVLXN93_e-FN0JLzpg1jb64Z_aEuyPjIfwbdQ" # Use your actual ID here
69
+ sheet = client.open_by_key(sheet_id).worksheet(sheet_name)
70
+
71
+ # Get all values from the sheet to check if the first row is empty (i.e., headers not created yet)
72
+ all_values = sheet.get_all_values()
73
 
74
  # Define headers based on the model type for accurate sheet saving
75
+ if sheet_name == "Trang tính1": # Full features model
76
  headers = ["Họ và tên", "MSV", "Khoa", "Dự báo", "Thời gian"] + [
77
  f"Số môn không thi - HK{i+1}" for i in range(6)] + [
78
  f"Số tín chỉ không thi - HK{i+1}" for i in range(6)] + [
 
85
  f"GPA - HK{i+1}" for i in range(6)] + [
86
  f"Xếp loại - HK{i+1}" for i in range(6)]
87
 
88
+ elif sheet_name == "Trang tính2": # Important features model
89
+ headers = ["Họ và tên", "MSV", "Khoa", "Dự báo", "Thời gian"] + [
90
  f"Số tín chỉ đạt - HK{i+1}" for i in range(6)] + [
91
  f"Số tín chỉ nợ - HK{i+1}" for i in range(6)] + [
92
  f"Điểm trung bình - HK{i+1}" for i in range(6)]
93
 
94
  # If the sheet is empty or if headers are missing, insert headers
95
+ if not all_values or len(all_values[0]) != len(headers): # Ensure number of columns matches expected headers
96
+ sheet.append_row(headers) # Create headers if missing
97
+
98
+ # Append data to the sheet
99
+ sheet.append_row(data_row)
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  # ===== HEADER =====
102
  st.markdown("<h1 style='text-align: center; color: #003366;'>🎓 DỰ ĐOÁN KHẢ NĂNG TỐT NGHIỆP ĐÚNG HẠN</h1>", unsafe_allow_html=True)
 
111
 
112
  sample_option = st.selectbox("📝 Chọn ví dụ:", ["Không ví dụ", "Dùng ví dụ mẫu ngành Công nghệ thông tin", "Dùng ví dụ mẫu ngành Kinh tế"])
113
 
114
+ # Ví dụ mẫu cho mô hình "Dùng toàn bộ dữ liệu"
115
  sample_cntt_example_full = {
116
+ "name": "Nguyễn Văn A",
117
+ "student_id": "10117367",
118
+ "major": "Công nghệ thông tin",
119
+ "semester_data": [
120
+ 0, 0, 0, 0, 17, 7, 7, 8.73, 0,
121
+ 0, 0, 0, 0, 17, 7, 7, 8.19, 0,
122
+ 0, 0, 0, 0, 17, 7, 7, 7.90, 0,
123
+ 0, 0, 0, 0, 17, 7, 7, 8.19, 0,
124
+ 0, 0, 0, 0, 19, 7, 6, 8.18, 0,
125
+ 0, 0, 5, 2, 19, 7, 5, 7.10, 1
126
+ ]
127
  }
128
 
129
+ # Ví dụ mẫu cho mô hình "Dùng mô hình đơn giản"
 
130
  sample_kinhte_example_simple = {
131
+ "name": "Trần Thị B",
132
+ "student_id": "11418092",
133
+ "major": "Kinh tế",
134
+ "semester_data": [
135
+ 17, 7, 7.64, # Học kỳ 1: Số tín chỉ đạt, Số tín chỉ nợ, GPA
136
+ 17, 7, 7.19, # Học kỳ 2: Số tín chỉ đạt, Số tín chỉ nợ, GPA
137
+ 17, 7, 6.94, # Học kỳ 3: Số tín chỉ đạt, Số tín chỉ nợ, GPA
138
+ 17, 7, 7.19, # Học kỳ 4: Số tín chỉ đạt, Số tín chỉ nợ, GPA
139
+ 19, 7, 7.65, # Học kỳ 5: Số tín chỉ đạt, Số tín chỉ nợ, GPA
140
+ 19, 7, 7.49 # Học kỳ 6: Số tín chỉ đạt, Số tín chỉ nợ, GPA
141
+ ]
142
  }
143
 
144
 
 
145
  # ===== Ví dụ cho mô hình "Dùng mô hình đơn giản" cho CNTT =====
146
  sample_cntt_example_simple = {
147
+ "name": "Nguyễn Văn B",
148
+ "student_id": "10117368",
149
+ "major": "Công nghệ thông tin",
150
+ "semester_data": [
151
+ 15, 8, 7.50, # Học kỳ 1: Số tín chỉ đạt, Số tín chỉ nợ, GPA
152
+ 17, 7, 8.10, # Học kỳ 2: Số tín chỉ đạt, Số tín chỉ nợ, GPA
153
+ 18, 7, 7.90, # Học kỳ 3: Số tín chỉ đạt, Số tín chỉ nợ, GPA
154
+ 17, 7, 7.80, # Học kỳ 4: Số tín chỉ đạt, Số tín chỉ nợ, GPA
155
+ 19, 8, 8.30, # Học kỳ 5: Số tín chỉ đạt, Số tín chỉ nợ, GPA
156
+ 19, 7, 7.20 # Học kỳ 6: Số tín chỉ đạt, Số tín chỉ nợ, GPA
157
+ ]
158
  }
159
 
160
  # ===== Ví dụ cho mô hình "Dùng mô hình đơn giản" cho Kinh tế =====
161
  sample_kinhte_example_full = {
162
+ "name": "Trần Thị C",
163
+ "student_id": "11418093",
164
+ "major": "Kinh tế",
165
+ "semester_data": [
166
+ 0, 0, 0, 0, 16, 6, 6, 7.00, 1,
167
+ 0, 0, 0, 0, 18, 7, 7, 8.20, 1,
168
+ 0, 0, 0, 0, 17, 7, 7, 7.80, 1,
169
+ 0, 0, 0, 0, 17, 7, 6, 7.90, 1,
170
+ 0, 0, 0, 0, 19, 8, 5, 8.10, 0,
171
+ 0, 0, 8, 2, 19, 7, 6, 7.30, 1
172
+ ]
173
  }
174
 
175
  # ===== Thông tin cá nhân =====
176
  if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin":
177
+ # Check model type to load appropriate example data
178
  if model_type == "Dùng toàn bộ đặc trưng":
179
  sample_data_personal = sample_cntt_example_full
180
  else: # Dùng đặc trưng quan trọng
181
  sample_data_personal = sample_cntt_example_simple
182
  name = st.text_input("👤 Họ và tên", value=sample_data_personal["name"])
183
+ student_id = st.text_input("🎓 Mã sinh viên", value=sample_data_personal["student_id"])
184
+ major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"], index=0)
185
  elif sample_option == "Dùng ví dụ mẫu ngành Kinh tế":
186
  # Check model type to load appropriate example data
187
  if model_type == "Dùng toàn bộ đặc trưng":
188
  sample_data_personal = sample_kinhte_example_full
189
  else: # Dùng đặc trưng quan trọng
190
  sample_data_personal = sample_kinhte_example_simple
191
+ name = st.text_input("👤 Họ và tên", value=sample_data_personal["name"])
192
+ student_id = st.text_input("🎓 Mã sinh viên", value=sample_data_personal["student_id"])
193
+ major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"], index=1)
194
  else:
195
+ name = st.text_input("👤 Họ và tên")
196
+ student_id = st.text_input("🎓 Mã sinh viên")
197
+ major = st.selectbox("📚 Ngành học", ["Công nghệ thông tin", "Kinh tế"])
 
198
 
199
  st.write("---")
200
 
201
  # ===== Nhập thông tin học kỳ =====
202
  def input_semester(semester_label, default_values=None):
203
+ with st.expander(f"📖 {semester_label}", expanded=True):
204
+ col1, col2 = st.columns(2)
205
+ with col1:
206
+ somon0thi = st.number_input("Số môn không thi", 0, value=default_values[0] if default_values else 0, key=f"sm0_{semester_label}")
207
+ sotc0thi = st.number_input("Số tín chỉ không thi", 0, value=default_values[1] if default_values else 0, key=f"tc0_{semester_label}")
208
+ sotcno = st.number_input("Số tín chỉ nợ", 0, value=default_values[2] if default_values else 0, key=f"tcno_{semester_label}")
209
+ mhno = st.number_input("Số môn không đạt", 0, value=default_values[3] if default_values else 0, key=f"mhno_{semester_label}")
210
+ sotc_qua = st.number_input("Số tín chỉ qua môn", 0, value=default_values[4] if default_values else 0, key=f"tcqua_{semester_label}")
211
+ with col2:
212
+ TCHK = st.number_input("Tổng tín chỉ học kỳ", 0, value=default_values[5] if default_values else 0, key=f"tchk_{semester_label}")
213
+ smhk = st.number_input("Số môn học kỳ", 0, value=default_values[6] if default_values else 0, key=f"smhk_{semester_label}")
214
+ mhpass = st.number_input("Số môn đạt", 0, value=default_values[7] if default_values else 0, key=f"mhpass_{semester_label}")
215
+ TBCHK = st.number_input("GPA", 0.0, 10.0, value=default_values[8] if default_values else 0.0, step=0.01, key=f"gpa_{semester_label}")
216
+ xep_loai_selected = st.selectbox("Xếp loại", list(range(7)), index=default_values[9] if default_values else 0, key=f"xeploai_{semester_label}")
217
+ return [somon0thi, sotc0thi, sotcno, mhno, sotc_qua, TCHK, smhk, mhpass, TBCHK, xep_loai_selected]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  # ===== Giao diện theo mô hình =====
220
  data = []
 
222
 
223
  # Mô hình 1: "Dùng toàn bộ dữ liệu"
224
  if model_type == "Dùng toàn bộ đặc trưng":
225
+ st.subheader("🔢 Nhập thông tin học kỳ chi tiết")
226
+ for idx, sem in enumerate(semesters):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  example_data = sample_cntt_example_full if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin" else sample_kinhte_example_full if sample_option == "Dùng ví dụ mẫu ngành Kinh tế" else None
228
+ default_values = example_data["semester_data"][idx*10:(idx+1)*10] if example_data else None
229
+ data += input_semester(sem, default_values) # Use the corrected function
230
+ nganh = 0 if major == "Công nghệ thông tin" else 1
231
+ final_features = np.array(data + [nganh]).reshape(1, -1)
 
232
 
233
  # Mô hình 2: "Dùng đặc trưng quan trọng"
234
  else: # model_type == "Dùng đặc trưng quan trọng"
235
+ st.subheader("✨ Nhập thông tin rút gọn")
236
+ for idx, sem in enumerate(semesters):
237
+ example_data = sample_cntt_example_simple if sample_option == "Dùng ví dụ mẫu ngành Công nghệ thông tin" else sample_kinhte_example_simple if sample_option == "Dùng ví dụ mẫu ngành Kinh tế" else None
238
+ default_values = example_data["semester_data"][idx*3:(idx+1)*3] if example_data else None
 
 
 
 
 
239
  with st.expander(f"📘 {sem}", expanded=True):
 
240
  col1, col2, col3 = st.columns(3)
241
  with col1:
242
+ sotc_qua = st.number_input("Số tín chỉ đạt", 0, value=default_values[0] if default_values else 0, key=f"tcqua_imp_{sem}")
 
243
  with col2:
244
+ sotcno = st.number_input("Số tín chỉ nợ", 0, value=default_values[1] if default_values else 0, key=f"tcno_imp_{sem}")
245
  with col3:
246
+ TBCHK = st.number_input("Điểm trung bình hệ 10", 0.0, 10.0, value=default_values[2] if default_values else 0.0, step=0.01, key=f"gpa_imp_{sem}")
247
+ data += [sotc_qua, sotcno, TBCHK]
248
+ final_features = np.array(data).reshape(1, -1)
 
 
 
 
249
 
250
  # ===== Predict =====
251
  if st.button("🎯 DỰ BÁO"):
252
+ if model_type == "Dùng toàn bộ đặc trưng":
253
+ prediction = model_full.predict(final_features)
254
+ sheet_name = "Trang tính1" # For full data model, save to Trang tính1
 
 
 
 
 
255
 
256
+ else: # model_type == "Dùng đặc trưng quan trọng"
257
+ prediction = model_important.predict(final_features)
258
+ sheet_name = "Trang tính2" # For important data model, save to Trang tính2
 
 
 
259
 
260
+ if prediction[0] == 1:
261
+ st.success(f"🎉 Chúc mừng bạn {name} - {major}! Bạn khả năng tốt nghiệp đúng hạn!")
262
+ st.balloons()
263
+ else:
264
+ st.error(f"⚠️ Bạn {name} - {major} cần cố gắng hơn! Có nguy cơ trễ hạn.")
265
+ st.snow()
266
 
267
+ save_to_gsheet(name, student_id, major, prediction, data, sheet_name) # Pass data to save function