Spaces:
Sleeping
Sleeping
| import os | |
| import sqlite3 | |
| import pandas as pd | |
| import numpy as np | |
| import gradio as gr | |
| from datetime import date | |
| # -------------------- STEP 1: Safe DB Path -------------------- | |
| if os.path.exists("D:"): # Local Windows setup | |
| DB_PATH = r"D:\attendance_space\attendance.db" | |
| else: # Hugging Face or Linux | |
| DB_PATH = os.path.join(os.path.dirname(__file__), "attendance.db") | |
| print(f"Using database at: {DB_PATH}") | |
| # -------------------- STEP 2: Initialize Database -------------------- | |
| def init_db(): | |
| os.makedirs(os.path.dirname(DB_PATH), exist_ok=True) | |
| conn = sqlite3.connect(DB_PATH, check_same_thread=False) | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS attendance ( | |
| StudentID TEXT, | |
| Subject TEXT, | |
| Date TEXT, | |
| Status TEXT | |
| ) | |
| """) | |
| conn.commit() | |
| conn.close() | |
| init_db() | |
| # -------------------- STEP 3: Core Functions -------------------- | |
| def add_attendance(student_id, subject, att_date, status): | |
| conn = sqlite3.connect(DB_PATH, check_same_thread=False) | |
| cursor = conn.cursor() | |
| cursor.execute("INSERT INTO attendance VALUES (?, ?, ?, ?)", | |
| (student_id, subject, att_date, status)) | |
| conn.commit() | |
| conn.close() | |
| return f"β Attendance added for Student {student_id}" | |
| def get_attendance_data(): | |
| conn = sqlite3.connect(DB_PATH, check_same_thread=False) | |
| df = pd.read_sql("SELECT * FROM attendance", conn) | |
| conn.close() | |
| return df | |
| def generate_summary(threshold=75): | |
| df = get_attendance_data() | |
| if df.empty: | |
| return pd.DataFrame(), pd.DataFrame() | |
| summary = ( | |
| df.groupby(['StudentID', 'Subject'])['Status'] | |
| .apply(lambda x: (x == 'Present').sum() / len(x) * 100) | |
| .reset_index(name='Attendance %') | |
| ) | |
| below_threshold = summary[summary['Attendance %'] < threshold] | |
| return summary, below_threshold | |
| def import_csv(file): | |
| try: | |
| df = pd.read_csv(file.name) | |
| conn = sqlite3.connect(DB_PATH, check_same_thread=False) | |
| df.to_sql("attendance", conn, if_exists="append", index=False) | |
| conn.close() | |
| return f"β Imported {len(df)} records." | |
| except Exception as e: | |
| return f"β Error: {e}" | |
| def export_csv(): | |
| df = get_attendance_data() | |
| export_path = os.path.join(os.path.dirname(DB_PATH), "attendance_export.csv") | |
| df.to_csv(export_path, index=False) | |
| return export_path | |
| def clear_db(): | |
| conn = sqlite3.connect(DB_PATH, check_same_thread=False) | |
| conn.execute("DELETE FROM attendance") | |
| conn.commit() | |
| conn.close() | |
| return "π Database cleared." | |
| # -------------------- STEP 4: Gradio UI -------------------- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## π Student Attendance Manager") | |
| with gr.Tab("β Add Attendance"): | |
| student_id = gr.Textbox(label="Student ID") | |
| subject = gr.Textbox(label="Subject") | |
| att_date = gr.Textbox(label="Date (YYYY-MM-DD)", value=str(date.today())) | |
| status = gr.Dropdown(["Present", "Absent"], label="Status") | |
| threshold = gr.Slider(0, 100, value=75, label="Threshold (%)") | |
| output_msg = gr.Textbox(label="Message") | |
| raw_df = gr.Dataframe(label="Raw Attendance") | |
| summary_df = gr.Dataframe(label="Summary") | |
| below_df = gr.Dataframe(label="Below Threshold") | |
| btn = gr.Button("Add & Refresh") | |
| btn.click( | |
| lambda sid, sub, dt, st, th: ( | |
| add_attendance(sid, sub, dt, st), | |
| get_attendance_data(), | |
| *generate_summary(th) | |
| ), | |
| [student_id, subject, att_date, status, threshold], | |
| [output_msg, raw_df, summary_df, below_df] | |
| ) | |
| with gr.Tab("π Reports"): | |
| threshold2 = gr.Slider(0, 100, value=75, label="Threshold (%)") | |
| summary_out = gr.Dataframe(label="Summary") | |
| below_out = gr.Dataframe(label="Below Threshold") | |
| btn_report = gr.Button("Generate Report") | |
| btn_report.click( | |
| lambda th: generate_summary(th), | |
| [threshold2], | |
| [summary_out, below_out] | |
| ) | |
| with gr.Tab("π€ Export Data"): | |
| export_btn = gr.Button("Export to CSV") | |
| export_msg = gr.Textbox(label="Export Path") | |
| export_btn.click(lambda: export_csv(), outputs=export_msg) | |
| with gr.Tab("π₯ Import Data"): | |
| file_in = gr.File(label="Upload CSV", file_types=[".csv"]) | |
| import_msg = gr.Textbox(label="Message") | |
| file_in.upload(lambda f: import_csv(f), file_in, import_msg) | |
| with gr.Tab("β Admin"): | |
| clear_btn = gr.Button("Clear Database") | |
| clear_msg = gr.Textbox(label="Message") | |
| clear_btn.click(lambda: clear_db(), outputs=clear_msg) | |
| # -------------------- STEP 5: Launch App -------------------- | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", # Required for Hugging Face Spaces | |
| server_port=int(os.environ.get("PORT", 7860)) | |
| ) | |