import gradio as gr
import os
import pandas as pd
from datetime import datetime
import calendar
from db import Database
from UserDetail import UserDetail
import image
import encdec
import plotly.graph_objects as go
import plotly.express as px
# Initialize database
db = Database()
# Custom CSS for beautiful styling
custom_css = """
.gradio-container {
font-family: 'Arial', sans-serif;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 2rem;
border-radius: 15px;
color: white;
text-align: center;
margin-bottom: 2rem;
}
.success-box {
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
padding: 1rem;
border-radius: 10px;
color: white;
text-align: center;
}
.error-box {
background: #ff6b6b;
padding: 1rem;
border-radius: 10px;
color: white;
}
"""
# ============================================
# HOME PAGE
# ============================================
def show_home():
"""Display home page with statistics"""
stats = db.get_statistics()
html = f"""
š Suthukeny Government High School
AI-Powered Student Management & Performance Analysis System
{stats['total_students']}
Total Students
{len(stats['class_wise'])}
Active Classes
{stats['students_with_marks']}
Students with Records
⨠Key Features
- š Face Recognition Login - Secure AI authentication
- š Complete Student Profiles - Photo ID with full details
- š Monthly Performance Tracking - 5 subjects with analytics
- š Visual Analytics - Beautiful interactive charts
- š Class Rankings - Top performers identification
- š¾ Persistent Storage - Data never lost
š How to Use
- Register Student: Upload photo and enter details
- Student Login: Use face recognition to access profile
- Update Marks: Teachers enter monthly exam scores
- View Reports: Analyze performance with charts
- Manage Students: Edit or update student information
Suthukeny Government High School
Empowering Education Through Technology š
"""
return html
# ============================================
# STUDENT REGISTRATION
# ============================================
def register_student(photo, name, dob, class_std, section, father_name, mother_name,
address, phone, email, blood_group):
"""Register a new student with face recognition"""
try:
# Validation
if photo is None:
return "ā Please upload a student photo", None, None
if not name or not dob or not class_std or not section:
return "ā Please fill all required fields (Name, DOB, Class, Section)", None, None
# Generate student ID
student_id = db.generate_student_id(class_std)
# Save image and create face encoding
success, message = image.save_image_from_path(photo, student_id)
if not success:
return f"ā {message}", None, None
# Create user detail object
user_detail = UserDetail(
student_id, name, str(dob), class_std, section,
father_name or "", mother_name or "", address or "",
phone or "", email or "", blood_group or ""
)
# Insert into database
success, db_message = db.insert_student(user_detail)
if success:
# Create student card HTML
card_html = f"""
ā
Registration Successful!
Student ID: {student_id}
Student registered successfully with face recognition!
Student Information
Name: {name}
Class: {class_std}-{section}
DOB: {dob}
Father: {father_name}
Mother: {mother_name}
Blood Group: {blood_group}
"""
return card_html, photo, f"Student ID: {student_id}"
else:
image.delete_image(student_id)
return f"ā {db_message}", None, None
except Exception as e:
return f"ā Error: {str(e)}", None, None
# ============================================
# STUDENT LOGIN
# ============================================
def login_with_face(photo):
"""Login student using face recognition"""
try:
if photo is None:
return "ā Please capture your photo", None
# Save temporary image
temp_path = image.save_temp_image_from_path(photo)
if not temp_path:
return "ā Failed to process image", None
# Recognize face
is_match, student_id, confidence, message = image.recognize_face(temp_path)
# Clean up
image.delete_temp_image()
if is_match:
# Get student details
student = db.get_student(student_id)
if student:
# Create profile HTML
profile_html = f"""
š Welcome, {student.student_name}!
Student ID: {student.student_id} | Class: {student.class_std}-{student.section}
Match Confidence: {confidence:.1f}%
š Personal Information
Name: {student.student_name}
Date of Birth: {student.dob}
Class: {student.class_std}-{student.section}
Father's Name: {student.father_name or 'Not specified'}
Mother's Name: {student.mother_name or 'Not specified'}
Address: {student.address or 'Not specified'}
Phone: {student.phone or 'Not specified'}
Email: {student.email or 'Not specified'}
Blood Group: {student.blood_group or 'Not specified'}
"""
# Get marks
marks_records = db.get_student_marks(student_id)
if marks_records:
marks_html = "š Recent Performance
"
for record in marks_records[:3]: # Show last 3 exams
marks_html += f"""
{record[0]} {record[1]}
Total: {record[12]}/500 | Percentage: {record[13]:.1f}%
{record[2]}: {record[3]} | {record[4]}: {record[5]} |
{record[6]}: {record[7]} | {record[8]}: {record[9]} |
{record[10]}: {record[11]}
"""
marks_html += "
"
profile_html += marks_html
return profile_html, student_id
else:
return "ā Student record not found", None
else:
return f"ā {message}\n\nš” Tip: Ensure good lighting and face the camera directly", None
except Exception as e:
return f"ā Error: {str(e)}", None
# ============================================
# MARKS MANAGEMENT
# ============================================
def get_students_in_class(class_std, section):
"""Get list of students in a class"""
students = db.get_all_students(class_filter=class_std)
class_students = [s for s in students if s[4] == section]
if class_students:
return gr.Dropdown(choices=[f"{s[1]} ({s[0]})" for s in class_students], label="Select Student")
else:
return gr.Dropdown(choices=[], label="No students in this class")
def save_marks(class_std, section, student_display, exam_month, exam_year,
subj1_name, subj1_marks, subj2_name, subj2_marks,
subj3_name, subj3_marks, subj4_name, subj4_marks,
subj5_name, subj5_marks):
"""Save student marks"""
try:
if not student_display:
return "ā Please select a student"
# Extract student ID from display string
student_id = student_display.split("(")[-1].strip(")")
# Validate inputs
subject_names = [subj1_name, subj2_name, subj3_name, subj4_name, subj5_name]
marks_list = [subj1_marks, subj2_marks, subj3_marks, subj4_marks, subj5_marks]
if any(not s.strip() for s in subject_names):
return "ā Please enter names for all subjects"
# Save marks
success, message = db.insert_marks(
student_id, exam_month, exam_year,
subject_names, marks_list
)
if success:
total = sum(marks_list)
percentage = (total / 500) * 100
return f"""
ā
Marks Saved Successfully!
Total: {total}/500 | Percentage: {percentage:.2f}%
"""
else:
return f"ā {message}"
except Exception as e:
return f"ā Error: {str(e)}"
# ============================================
# REPORTS
# ============================================
def generate_class_report(class_std, exam_year):
"""Generate class performance report"""
try:
performance = db.get_class_performance(
class_std,
exam_year=exam_year if exam_year != "All" else None
)
if not performance:
return "š No performance data available for selected filters", None
# Create DataFrame
df = pd.DataFrame(performance, columns=[
'Student ID', 'Name', 'Month', 'Year', 'Total', 'Percentage'
])
# Calculate average
avg_percentage = df['Percentage'].mean()
# Create report HTML
report_html = f"""
š Class {class_std} Performance Report
Average: {avg_percentage:.1f}%
"""
# Create bar chart
fig = go.Figure(data=[
go.Bar(
x=df['Name'],
y=df['Percentage'],
marker=dict(
color=df['Percentage'],
colorscale='RdYlGn',
showscale=True
),
text=df['Percentage'].round(1),
textposition='auto',
)
])
fig.update_layout(
title=f"Class {class_std} Student Performance",
xaxis_title="Student",
yaxis_title="Percentage",
height=500
)
return report_html, fig
except Exception as e:
return f"ā Error: {str(e)}", None
# ============================================
# ADMIN PANEL
# ============================================
def admin_login(password):
"""Verify admin password"""
if password == encdec.get_admin_password():
stats = db.get_statistics()
html = f"""
ā
Admin Access Granted
š System Statistics
Total Students: {stats['total_students']}
Active Classes: {len(stats['class_wise'])}
Students with Marks: {stats['students_with_marks']}
Class Distribution:
"""
for class_name, count in stats['class_wise']:
html += f"- Class {class_name}: {count} students
"
html += """
ā ļø Data Management
Use with caution! Data operations are permanent.
"""
return html
else:
return """
ā Incorrect Password
"""
# ============================================
# CREATE GRADIO INTERFACE
# ============================================
with gr.Blocks(css=custom_css, title="Suthukeny Govt High School", theme=gr.themes.Soft()) as app:
gr.Markdown("""
# š Suthukeny Government High School
## AI-Powered Student Management & Performance Analysis System
""")
with gr.Tabs():
# HOME TAB
with gr.Tab("š Home"):
home_output = gr.HTML(show_home())
gr.Button("š Refresh Statistics").click(
fn=show_home,
outputs=home_output
)
# REGISTRATION TAB
with gr.Tab("š Register Student"):
gr.Markdown("### Register New Student")
gr.Markdown("Upload a clear, front-facing photo of the student")
with gr.Row():
with gr.Column(scale=1):
reg_photo = gr.Image(type="filepath", label="Student Photo", sources=["upload", "webcam"])
with gr.Column(scale=2):
with gr.Group():
gr.Markdown("#### Required Information")
reg_name = gr.Textbox(label="Student Name *", placeholder="Enter full name")
with gr.Row():
reg_dob = gr.Textbox(label="Date of Birth * (YYYY-MM-DD)", placeholder="2010-01-01")
reg_class = gr.Dropdown(choices=["6", "7", "8", "9", "10", "11", "12"], label="Class *")
reg_section = gr.Dropdown(choices=["A", "B", "C"], label="Section *")
with gr.Group():
gr.Markdown("#### Family Information")
with gr.Row():
reg_father = gr.Textbox(label="Father's Name", placeholder="Optional")
reg_mother = gr.Textbox(label="Mother's Name", placeholder="Optional")
with gr.Group():
gr.Markdown("#### Contact Information")
reg_address = gr.Textbox(label="Address", placeholder="Optional", lines=2)
with gr.Row():
reg_phone = gr.Textbox(label="Phone", placeholder="Optional")
reg_email = gr.Textbox(label="Email", placeholder="Optional")
reg_blood = gr.Dropdown(choices=["", "A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"],
label="Blood Group")
reg_button = gr.Button("ā
Register Student", variant="primary", size="lg")
reg_output = gr.HTML()
reg_photo_display = gr.Image(label="Registered Student", visible=False)
reg_id_display = gr.Textbox(label="Student ID", visible=False)
reg_button.click(
fn=register_student,
inputs=[reg_photo, reg_name, reg_dob, reg_class, reg_section,
reg_father, reg_mother, reg_address, reg_phone, reg_email, reg_blood],
outputs=[reg_output, reg_photo_display, reg_id_display]
)
# LOGIN TAB
with gr.Tab("š Student Login"):
gr.Markdown("### Face Recognition Login")
gr.Markdown("šø Position your face in the center and click capture")
with gr.Row():
with gr.Column(scale=1):
login_photo = gr.Image(type="filepath", label="Capture Your Face", sources=["webcam"])
login_button = gr.Button("š Login with Face", variant="primary", size="lg")
with gr.Column(scale=2):
login_output = gr.HTML()
login_student_id = gr.Textbox(label="Logged in Student ID", visible=False)
login_button.click(
fn=login_with_face,
inputs=login_photo,
outputs=[login_output, login_student_id]
)
# MARKS ENTRY TAB
with gr.Tab("š Marks Entry"):
gr.Markdown("### Enter Student Marks")
with gr.Row():
marks_class = gr.Dropdown(choices=["6", "7", "8", "9", "10", "11", "12"], label="Class")
marks_section = gr.Dropdown(choices=["A", "B", "C"], label="Section")
marks_student = gr.Dropdown(label="Select Student", choices=[])
# Update student dropdown when class/section changes
marks_class.change(
fn=get_students_in_class,
inputs=[marks_class, marks_section],
outputs=marks_student
)
marks_section.change(
fn=get_students_in_class,
inputs=[marks_class, marks_section],
outputs=marks_student
)
with gr.Row():
marks_month = gr.Dropdown(
choices=list(calendar.month_name)[1:],
label="Exam Month",
value=calendar.month_name[datetime.now().month]
)
marks_year = gr.Dropdown(
choices=[str(y) for y in range(datetime.now().year - 1, datetime.now().year + 2)],
label="Exam Year",
value=str(datetime.now().year)
)
gr.Markdown("#### Enter Marks (Out of 100)")
with gr.Row():
with gr.Column():
subj1_name = gr.Textbox(label="Subject 1 Name", value="Tamil")
subj1_marks = gr.Number(label="Marks", value=0, minimum=0, maximum=100)
with gr.Column():
subj2_name = gr.Textbox(label="Subject 2 Name", value="English")
subj2_marks = gr.Number(label="Marks", value=0, minimum=0, maximum=100)
with gr.Row():
with gr.Column():
subj3_name = gr.Textbox(label="Subject 3 Name", value="Mathematics")
subj3_marks = gr.Number(label="Marks", value=0, minimum=0, maximum=100)
with gr.Column():
subj4_name = gr.Textbox(label="Subject 4 Name", value="Science")
subj4_marks = gr.Number(label="Marks", value=0, minimum=0, maximum=100)
with gr.Row():
with gr.Column():
subj5_name = gr.Textbox(label="Subject 5 Name", value="Social Science")
subj5_marks = gr.Number(label="Marks", value=0, minimum=0, maximum=100)
with gr.Column():
save_marks_btn = gr.Button("š¾ Save Marks", variant="primary", size="lg")
marks_output = gr.HTML()
save_marks_btn.click(
fn=save_marks,
inputs=[marks_class, marks_section, marks_student, marks_month, marks_year,
subj1_name, subj1_marks, subj2_name, subj2_marks,
subj3_name, subj3_marks, subj4_name, subj4_marks,
subj5_name, subj5_marks],
outputs=marks_output
)
# REPORTS TAB
with gr.Tab("š Reports"):
gr.Markdown("### Performance Reports")
with gr.Row():
report_class = gr.Dropdown(choices=["6", "7", "8", "9", "10", "11", "12"],
label="Select Class", value="6")
report_year = gr.Dropdown(choices=["All"] + [str(y) for y in range(datetime.now().year - 2, datetime.now().year + 1)],
label="Exam Year", value=str(datetime.now().year))
report_btn = gr.Button("š Generate Report", variant="primary")
report_output = gr.HTML()
report_chart = gr.Plot()
report_btn.click(
fn=generate_class_report,
inputs=[report_class, report_year],
outputs=[report_output, report_chart]
)
# ADMIN TAB
with gr.Tab("š§ Admin Panel"):
gr.Markdown("### Admin Access")
gr.Markdown("ā ļø Authorized personnel only")
admin_password = gr.Textbox(label="Admin Password", type="password")
admin_login_btn = gr.Button("š Login", variant="primary")
admin_output = gr.HTML()
admin_login_btn.click(
fn=admin_login,
inputs=admin_password,
outputs=admin_output
)
gr.Markdown("""
---
Suthukeny Government High School
Empowering Education Through Technology š
""")
# Launch the app
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860)