PraneshJs commited on
Commit
cfb4845
Β·
verified Β·
1 Parent(s): 782aeba

added exact details of Reward Point

Browse files
Files changed (1) hide show
  1. app.py +234 -15
app.py CHANGED
@@ -7,7 +7,7 @@ from google_auth_oauthlib.flow import InstalledAppFlow
7
  import json
8
  import gradio as gr
9
  import time
10
- from datetime import datetime, timedelta
11
  from pytz import timezone
12
  import threading
13
  from dotenv import load_dotenv
@@ -117,6 +117,204 @@ def get_studentwise_data(spreadsheet):
117
  print(f"❌ Error loading Studentwise Reward Points: {str(e)}")
118
  return None
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  # Function to get details sheet information
121
  def get_details_info(spreadsheet):
122
  try:
@@ -206,7 +404,6 @@ STUDENTWISE_SHEET_ID = os.getenv('STUDENTWISE_SHEET_ID') # Studentwise Reward P
206
  if not MAIN_SHEET_ID:
207
  raise ValueError("GOOGLE_SHEET_ID environment variable is required")
208
 
209
-
210
  # Open both spreadsheets
211
  main_spreadsheet = client.open_by_key(MAIN_SHEET_ID)
212
  studentwise_spreadsheet = client.open_by_key(STUDENTWISE_SHEET_ID)
@@ -236,26 +433,28 @@ sheet_configs = [
236
  {"gid": 400900059, "name": "Sheet_20"}
237
  ]
238
 
239
- # πŸ•’ GLOBAL DATA CACHE WITH 12-HOUR AUTO-REFRESH
240
  data_cache = {
241
  "combined_df": None,
242
  "studentwise_data": None,
243
  "details_info": None,
 
244
  "last_update": None,
245
  "cache_duration_hours": 12, # 12 hours cache
246
  "is_loading": False
247
  }
248
 
249
  def load_all_data():
250
- """Load and cache all data from Google Sheets"""
251
  global data_cache
252
 
253
  if data_cache["is_loading"]:
254
  print("⏳ Data loading already in progress...")
255
- return data_cache["combined_df"], data_cache["studentwise_data"], data_cache["details_info"]
 
256
 
257
  data_cache["is_loading"] = True
258
- print(f"πŸ”„ Loading fresh data from {len(sheet_configs)} Google Sheets...")
259
  start_time = time.time()
260
 
261
  try:
@@ -315,23 +514,28 @@ def load_all_data():
315
  # Load details info from main spreadsheet
316
  details_info = get_details_info(main_spreadsheet)
317
 
 
 
 
318
  # Update cache
319
  data_cache["combined_df"] = combined_df
320
  data_cache["studentwise_data"] = studentwise_data
321
  data_cache["details_info"] = details_info
 
322
  data_cache["last_update"] = datetime.now()
323
 
324
  load_time = time.time() - start_time
325
  print(f"⏱️ Data loaded and cached in {load_time:.2f} seconds")
326
  print(f"πŸ“Š Next auto-refresh in {data_cache['cache_duration_hours']} hours")
327
 
328
- return combined_df, studentwise_data, details_info
329
 
330
  except Exception as e:
331
  print(f"❌ Error loading data: {str(e)}")
332
  return (data_cache.get("combined_df", pd.DataFrame()),
333
  data_cache.get("studentwise_data", None),
334
- data_cache.get("details_info", None))
 
335
 
336
  finally:
337
  data_cache["is_loading"] = False
@@ -350,7 +554,8 @@ def get_cached_data():
350
  else:
351
  cache_age_hours = (now - data_cache["last_update"]).total_seconds() / 3600
352
  print(f"πŸš€ Using cached data (age: {cache_age_hours:.1f} hours)")
353
- return data_cache["combined_df"], data_cache["studentwise_data"], data_cache["details_info"]
 
354
 
355
  def auto_refresh_worker():
356
  """Background worker to auto-refresh data every 12 hours"""
@@ -385,7 +590,6 @@ def get_detailed_student_points(roll_no, studentwise_data):
385
 
386
  output = []
387
  output.append("\n")
388
- output.append("=" * 80)
389
  output.append("πŸ† REWARD POINTS BREAKDOWN")
390
  output.append("=" * 80)
391
 
@@ -457,7 +661,7 @@ def search_student(roll_no):
457
  roll_no = roll_no.strip().upper()
458
 
459
  # Get cached data (fast response, auto-refreshes every 12 hours)
460
- combined_df, studentwise_data, details_info = get_cached_data()
461
 
462
  if combined_df.empty:
463
  return "❌ No data available from Google Sheets"
@@ -481,12 +685,11 @@ def search_student(roll_no):
481
  student_name = str(record.get('STUDENT NAME', 'Unknown')).strip()
482
  student_year = str(record.get('YEAR', '')).strip()
483
 
484
- # Time Zone conversion
485
  ist = timezone("Asia/Kolkata")
486
  now_ist = datetime.now(ist).strftime("%Y-%m-%d %H:%M:%S")
487
-
488
  # Log to see which roll number and student name is searched by user
489
- print(f"Roll No Searched: {roll_no} | Student Name: {student_name} | Time: {now_ist}")
490
 
491
  # Format output - Simplified version
492
  output = []
@@ -544,11 +747,18 @@ def search_student(roll_no):
544
  output.append(" Keep up the great work! 🌟")
545
  output.append(" Refer Reward points Breakdown for more details")
546
 
 
 
 
 
 
 
547
  # Add detailed points breakdown from studentwise data
548
  detailed_points = get_detailed_student_points(roll_no, studentwise_data)
549
  if detailed_points:
550
  output.append(detailed_points)
551
 
 
552
  # Add last updated info
553
  if details_info and 'last_updated' in details_info:
554
  output.append("\n" + "-" * 60)
@@ -573,7 +783,7 @@ def search_student(roll_no):
573
 
574
  # Function to get system information
575
  def get_system_info():
576
- combined_df, studentwise_data, details_info = get_cached_data()
577
 
578
  if not details_info:
579
  return "❌ No system information available"
@@ -611,6 +821,14 @@ def get_system_info():
611
  output.append("-" * 40)
612
  output.append(details_info['last_updated'])
613
 
 
 
 
 
 
 
 
 
614
  # Cache info
615
  if data_cache["last_update"]:
616
  cache_age = datetime.now() - data_cache["last_update"]
@@ -701,6 +919,7 @@ with gr.Blocks(title="Student Reward Points Check", theme=gr.themes.Soft()) as a
701
  elem_id="footer"
702
  )
703
 
 
704
  # Launch the app
705
  if __name__ == "__main__":
706
  print("πŸš€ Launching Gradio interface...")
 
7
  import json
8
  import gradio as gr
9
  import time
10
+ from datetime import datetime
11
  from pytz import timezone
12
  import threading
13
  from dotenv import load_dotenv
 
117
  print(f"❌ Error loading Studentwise Reward Points: {str(e)}")
118
  return None
119
 
120
+ # NEW FUNCTION: Load and cache reward points activity data
121
+ def load_reward_points_data():
122
+ """Load and cache reward points activity data"""
123
+ try:
124
+ # Get the reward points sheet ID from environment
125
+ REWARD_POINTS_SHEET_ID = os.getenv('REWARD_POINTS_SHEET_ID')
126
+
127
+ if not REWARD_POINTS_SHEET_ID:
128
+ print("⚠️ REWARD_POINTS_SHEET_ID not found in environment variables")
129
+ return None
130
+
131
+ client = authorize()
132
+ spreadsheet = client.open_by_key(REWARD_POINTS_SHEET_ID)
133
+ worksheet = spreadsheet.get_worksheet_by_id(1113414351) # Activity Sheet GID
134
+ all_values = worksheet.get_all_values()
135
+
136
+ if not all_values or len(all_values) < 2:
137
+ print("⚠️ Reward Points sheet doesn't have enough data")
138
+ return None
139
+
140
+ # First row is header
141
+ headers = all_values[0]
142
+ df = pd.DataFrame(all_values[1:], columns=headers)
143
+
144
+ if df.empty:
145
+ print("⚠️ Reward Points sheet is empty")
146
+ return None
147
+
148
+ print(f"βœ… Loaded {len(df)} rows from Reward Points Entry sheet")
149
+ return df
150
+
151
+ except Exception as e:
152
+ print(f"❌ Error loading Reward Points data: {str(e)}")
153
+ return None
154
+
155
+ # MODIFIED FUNCTION: Get activity details from cached data
156
+ def get_activity_details(roll_no, reward_points_df):
157
+ """Get activity details for a specific roll number from cached reward points data in breakdown format"""
158
+ try:
159
+ if reward_points_df is None or reward_points_df.empty:
160
+ return ""
161
+
162
+ # Normalize roll number for search
163
+ roll_no_search = roll_no.strip().upper()
164
+
165
+ # Try to find the roll number column
166
+ roll_col = None
167
+ for col in reward_points_df.columns:
168
+ if 'roll' in col.lower() and 'no' in col.lower():
169
+ roll_col = col
170
+ break
171
+
172
+ if not roll_col:
173
+ # Use first column as roll number column
174
+ roll_col = reward_points_df.columns[0]
175
+
176
+ # Create a copy to avoid modifying the original cached data
177
+ df = reward_points_df.copy()
178
+
179
+ # Normalize the roll number column
180
+ df[roll_col] = df[roll_col].astype(str).str.strip().str.upper()
181
+
182
+ # Filter rows by roll number
183
+ student_rows = df[df[roll_col] == roll_no_search]
184
+
185
+ if student_rows.empty:
186
+ # Try partial matching
187
+ partial_matches = df[df[roll_col].str.contains(roll_no_search, na=False)]
188
+ if not partial_matches.empty:
189
+ student_rows = partial_matches
190
+ else:
191
+ return ""
192
+
193
+ if student_rows.empty:
194
+ return ""
195
+
196
+ # Get student info from first record
197
+ first_record = student_rows.iloc[0]
198
+ student_name = first_record.get('NAME OF THE STUDENT', 'N/A')
199
+ student_year = first_record.get('YEAR OF STUDY', 'N/A')
200
+ student_dept = first_record.get('DEPARTMENT', 'N/A')
201
+
202
+ # Calculate activity summary by type
203
+ activity_summary = {}
204
+ activity_count = {}
205
+ total_points = 0
206
+
207
+ for _, row in student_rows.iterrows():
208
+ activity_type = str(row.get('Activity Type', 'N/A'))
209
+ reward_points = str(row.get('Reward Points', '0'))
210
+
211
+ # Convert points to float
212
+ try:
213
+ points_val = float(reward_points.replace(',', '')) if reward_points else 0
214
+ total_points += points_val
215
+ except:
216
+ points_val = 0
217
+
218
+ # Track activity summary
219
+ if activity_type in activity_summary:
220
+ activity_summary[activity_type] += points_val
221
+ activity_count[activity_type] += 1
222
+ else:
223
+ activity_summary[activity_type] = points_val
224
+ activity_count[activity_type] = 1
225
+
226
+ # Format output in breakdown style
227
+ output = []
228
+ # Define all possible activity categories in order
229
+ activity_categories = [
230
+ "INITIAL POINTS / CARRY-OVER",
231
+ "TECHNICAL EVENTS",
232
+ "SKILLS",
233
+ "ASSIGNMENTS",
234
+ "INTERVIEW",
235
+ "TECHNICAL SOCIETY ACTIVITIES",
236
+ "P SKILL",
237
+ "TAC",
238
+ "SPECIAL LAB INITIATIVES",
239
+ "EXTRA-CURRICULAR ACTIVITIES",
240
+ "STUDENT INITIATIVES",
241
+ "EXTERNAL EVENTS",
242
+ "EXTERNAL TECHNICAL EVENTS"
243
+ ]
244
+
245
+ # Map activity types to standard categories (case-insensitive matching)
246
+ category_mapping = {}
247
+ for activity_type in activity_summary.keys():
248
+ activity_upper = activity_type.upper()
249
+ matched_category = None
250
+
251
+ # Try exact matching first
252
+ for category in activity_categories:
253
+ if category.upper() in activity_upper or activity_upper in category.upper():
254
+ matched_category = category
255
+ break
256
+
257
+ # If no exact match, use the original activity type
258
+ if not matched_category:
259
+ matched_category = activity_type
260
+
261
+ category_mapping[activity_type] = matched_category
262
+
263
+ # Group activities by mapped categories
264
+ final_summary = {}
265
+ final_count = {}
266
+
267
+ for activity_type, points in activity_summary.items():
268
+ category = category_mapping[activity_type]
269
+ if category in final_summary:
270
+ final_summary[category] += points
271
+ final_count[category] += activity_count[activity_type]
272
+ else:
273
+ final_summary[category] = points
274
+ final_count[category] = activity_count[activity_type]
275
+
276
+ # Display all categories (including zeros)
277
+ for category in activity_categories:
278
+ count = final_count.get(category, 0)
279
+ points = final_summary.get(category, 0.0)
280
+
281
+
282
+ # Add any categories not in the standard list
283
+ for category, points in final_summary.items():
284
+ if category not in activity_categories:
285
+ count = final_count.get(category, 0)
286
+
287
+
288
+ # Add detailed activity list if needed
289
+ if len(student_rows) <= 20: # Only show detailed list for reasonable number of activities
290
+ output.append("")
291
+ output.append("=" * 80)
292
+ output.append("πŸ“‹ DETAILED ACTIVITY LIST")
293
+ output.append("=" * 80)
294
+
295
+ for idx, (_, row) in enumerate(student_rows.iterrows(), 1):
296
+ activity_type = str(row.get('Activity Type', 'N/A'))
297
+ activity_name = str(row.get('Activity Name', 'N/A'))
298
+ reward_points = str(row.get('Reward Points', '0'))
299
+
300
+ try:
301
+ points_val = float(reward_points.replace(',', '')) if reward_points else 0
302
+ except:
303
+ points_val = 0
304
+
305
+ # Truncate long names for display
306
+ display_name = activity_name[:50] + "..." if len(activity_name) > 63 else activity_name
307
+ output.append(f"{idx:2d}. {activity_type}: {display_name} - {points_val:.2f} pts")
308
+
309
+
310
+ output.append("=" * 80)
311
+
312
+ return "\n".join(output)
313
+
314
+ except Exception as e:
315
+ print(f"❌ Error fetching activity details: {str(e)}")
316
+ return ""
317
+
318
  # Function to get details sheet information
319
  def get_details_info(spreadsheet):
320
  try:
 
404
  if not MAIN_SHEET_ID:
405
  raise ValueError("GOOGLE_SHEET_ID environment variable is required")
406
 
 
407
  # Open both spreadsheets
408
  main_spreadsheet = client.open_by_key(MAIN_SHEET_ID)
409
  studentwise_spreadsheet = client.open_by_key(STUDENTWISE_SHEET_ID)
 
433
  {"gid": 400900059, "name": "Sheet_20"}
434
  ]
435
 
436
+ # πŸ•’ GLOBAL DATA CACHE WITH 12-HOUR AUTO-REFRESH (NOW INCLUDES REWARD POINTS DATA)
437
  data_cache = {
438
  "combined_df": None,
439
  "studentwise_data": None,
440
  "details_info": None,
441
+ "reward_points_df": None, # NEW: Cache for reward points data
442
  "last_update": None,
443
  "cache_duration_hours": 12, # 12 hours cache
444
  "is_loading": False
445
  }
446
 
447
  def load_all_data():
448
+ """Load and cache all data from Google Sheets (including reward points data)"""
449
  global data_cache
450
 
451
  if data_cache["is_loading"]:
452
  print("⏳ Data loading already in progress...")
453
+ return (data_cache["combined_df"], data_cache["studentwise_data"],
454
+ data_cache["details_info"], data_cache["reward_points_df"])
455
 
456
  data_cache["is_loading"] = True
457
+ print(f"πŸ”„ Loading fresh data from {len(sheet_configs)} Google Sheets + Reward Points sheet...")
458
  start_time = time.time()
459
 
460
  try:
 
514
  # Load details info from main spreadsheet
515
  details_info = get_details_info(main_spreadsheet)
516
 
517
+ # NEW: Load reward points activity data
518
+ reward_points_df = load_reward_points_data()
519
+
520
  # Update cache
521
  data_cache["combined_df"] = combined_df
522
  data_cache["studentwise_data"] = studentwise_data
523
  data_cache["details_info"] = details_info
524
+ data_cache["reward_points_df"] = reward_points_df # NEW: Cache reward points data
525
  data_cache["last_update"] = datetime.now()
526
 
527
  load_time = time.time() - start_time
528
  print(f"⏱️ Data loaded and cached in {load_time:.2f} seconds")
529
  print(f"πŸ“Š Next auto-refresh in {data_cache['cache_duration_hours']} hours")
530
 
531
+ return combined_df, studentwise_data, details_info, reward_points_df
532
 
533
  except Exception as e:
534
  print(f"❌ Error loading data: {str(e)}")
535
  return (data_cache.get("combined_df", pd.DataFrame()),
536
  data_cache.get("studentwise_data", None),
537
+ data_cache.get("details_info", None),
538
+ data_cache.get("reward_points_df", None))
539
 
540
  finally:
541
  data_cache["is_loading"] = False
 
554
  else:
555
  cache_age_hours = (now - data_cache["last_update"]).total_seconds() / 3600
556
  print(f"πŸš€ Using cached data (age: {cache_age_hours:.1f} hours)")
557
+ return (data_cache["combined_df"], data_cache["studentwise_data"],
558
+ data_cache["details_info"], data_cache["reward_points_df"])
559
 
560
  def auto_refresh_worker():
561
  """Background worker to auto-refresh data every 12 hours"""
 
590
 
591
  output = []
592
  output.append("\n")
 
593
  output.append("πŸ† REWARD POINTS BREAKDOWN")
594
  output.append("=" * 80)
595
 
 
661
  roll_no = roll_no.strip().upper()
662
 
663
  # Get cached data (fast response, auto-refreshes every 12 hours)
664
+ combined_df, studentwise_data, details_info, reward_points_df = get_cached_data()
665
 
666
  if combined_df.empty:
667
  return "❌ No data available from Google Sheets"
 
685
  student_name = str(record.get('STUDENT NAME', 'Unknown')).strip()
686
  student_year = str(record.get('YEAR', '')).strip()
687
 
688
+ # Time zone Conversion
689
  ist = timezone("Asia/Kolkata")
690
  now_ist = datetime.now(ist).strftime("%Y-%m-%d %H:%M:%S")
 
691
  # Log to see which roll number and student name is searched by user
692
+ print(f"Roll No Searched: {roll_no} | Student Name: {student_name} | Time (IST): {now_ist}")
693
 
694
  # Format output - Simplified version
695
  output = []
 
747
  output.append(" Keep up the great work! 🌟")
748
  output.append(" Refer Reward points Breakdown for more details")
749
 
750
+
751
+ # MODIFIED: Add individual activity details from cached reward points data
752
+ activity_details = get_activity_details(roll_no, reward_points_df)
753
+ if activity_details:
754
+ output.append(activity_details)
755
+
756
  # Add detailed points breakdown from studentwise data
757
  detailed_points = get_detailed_student_points(roll_no, studentwise_data)
758
  if detailed_points:
759
  output.append(detailed_points)
760
 
761
+
762
  # Add last updated info
763
  if details_info and 'last_updated' in details_info:
764
  output.append("\n" + "-" * 60)
 
783
 
784
  # Function to get system information
785
  def get_system_info():
786
+ combined_df, studentwise_data, details_info, reward_points_df = get_cached_data()
787
 
788
  if not details_info:
789
  return "❌ No system information available"
 
821
  output.append("-" * 40)
822
  output.append(details_info['last_updated'])
823
 
824
+ # NEW: Add reward points data info
825
+ if reward_points_df is not None:
826
+ output.append(f"\nREWARD POINTS DATA:")
827
+ output.append("-" * 40)
828
+ output.append(f"Total activity records: {len(reward_points_df)}")
829
+ unique_students = reward_points_df.iloc[:, 0].nunique() if not reward_points_df.empty else 0
830
+ output.append(f"Students with activities: {unique_students}")
831
+
832
  # Cache info
833
  if data_cache["last_update"]:
834
  cache_age = datetime.now() - data_cache["last_update"]
 
919
  elem_id="footer"
920
  )
921
 
922
+
923
  # Launch the app
924
  if __name__ == "__main__":
925
  print("πŸš€ Launching Gradio interface...")