Spaces:
Sleeping
Sleeping
| import matplotlib.pyplot as plt | |
| from fpdf import FPDF | |
| from datetime import datetime | |
| from huggingfaceModel import generate_dropout_insights | |
| #rom ollamaModel import generate_dropout_insights | |
| import re | |
| import os | |
| def format_key(key): | |
| """Format keys to be more readable by capitalizing and removing underscores.""" | |
| return key.replace("_", " ").title() | |
| def remove_unsupported_characters(text): | |
| """Removes emojis and unsupported Unicode characters for PDF compatibility.""" | |
| return text.encode("ascii", "ignore").decode() | |
| def generate_pdf(input_data, dropout_risk, summary): | |
| """Generates a structured, professional PDF report for dropout prediction results.""" | |
| pdf = FPDF() | |
| pdf.add_page() | |
| # ๐น Check if DejaVuSans font files exist | |
| if os.path.exists("DejaVuSans.ttf") and os.path.exists("DejaVuSans-Bold.ttf") and os.path.exists("DejaVuSans-Oblique.ttf"): | |
| font_name = "DejaVu" | |
| pdf.add_font("DejaVu", "", "Dejavu/DejaVuSans.ttf", uni=True) | |
| pdf.add_font("DejaVu", "B", "Dejavu/DejaVuSans-Bold.ttf", uni=True) | |
| pdf.add_font("DejaVu", "I", "Dejavu/DejaVuSans-Oblique.ttf", uni=True) | |
| else: | |
| font_name = "Arial" # Use default Arial if DejaVu fonts are missing | |
| # ๐น Cover Page | |
| pdf.set_font(font_name, "B", 20) | |
| pdf.cell(200, 15, "AI-DRIVEN DROPOUT PREDICTION AND PREVENTION TOOL", ln=True, align="C") | |
| pdf.set_font(font_name, "I", 12) | |
| pdf.cell(200, 10, "Generated by: AI Dropout Predictor System", ln=True, align="C") | |
| pdf.cell(200, 10, f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align="C") | |
| pdf.ln(20) | |
| pdf.set_font(font_name, "B", 16) | |
| pdf.cell(200, 10, "Confidential Report", ln=True, align="C") | |
| pdf.ln(10) | |
| pdf.set_font(font_name, "I", 12) | |
| pdf.cell(200, 10, "This document contains confidential student information and predictive analysis.", ln=True, align="C") | |
| pdf.add_page() | |
| # ๐น Student Information Section | |
| pdf.set_font(font_name, "B", 14) | |
| pdf.cell(200, 10, "Student Information", ln=True, align="L") | |
| pdf.ln(5) | |
| pdf.set_font(font_name, "", 12) | |
| for key, value in input_data.items(): | |
| formatted_key = key.replace("_", " ").title() | |
| pdf.cell(90, 8, f"{formatted_key}:", border=1, align="L") | |
| pdf.cell(100, 8, str(value), border=1, align="L") | |
| pdf.ln(8) | |
| pdf.ln(10) | |
| pdf.add_page() | |
| # ๐น Dropout Risk Score Section | |
| pdf.set_font(font_name, "B", 14) | |
| pdf.cell(200, 10, "Predicted Dropout Risk Score", ln=True, align="L") | |
| pdf.ln(5) | |
| pdf.set_font(font_name, "B", 16) | |
| pdf.set_fill_color(240, 240, 240) | |
| pdf.cell(200, 15, f" Dropout Risk Score: {dropout_risk}/10 ", ln=True, align="L", border=1, fill=True) | |
| pdf.ln(10) | |
| # ๐น Dropout Prediction Graph | |
| pdf.set_font(font_name, "B", 14) | |
| pdf.cell(200, 10, "Dropout Risk Analysis Graph", ln=True, align="C") | |
| pdf.ln(5) | |
| if os.path.exists("dropout_plot.png"): | |
| pdf.image("dropout_plot.png", x=50, w=100) | |
| else: | |
| pdf.cell(200, 10, "Graph Unavailable", ln=True, align="C") | |
| pdf.ln(20) | |
| pdf.add_page() | |
| # ๐น Summary Section | |
| pdf.set_font(font_name, "B", 14) | |
| pdf.cell(200, 10, "Summary of Student Data", ln=True, align="C") | |
| pdf.ln(5) | |
| pdf.set_font(font_name, "", 12) | |
| cleaned_summary = remove_unsupported_characters(summary) | |
| pdf.multi_cell(0, 7, cleaned_summary, align="L") | |
| # ๐น Disclaimer | |
| pdf.set_y(-30) | |
| pdf.set_font(font_name, "I", 10) | |
| pdf.cell(200, 10, "Disclaimer:", ln=True, align="L") | |
| pdf.multi_cell(0, 7, "This report is generated using predictive analysis. It does not guarantee actual dropout behavior but serves as a guideline for early intervention.", align="L") | |
| # ๐น Save PDF | |
| pdf_filename = "Dropout_Report.pdf" | |
| pdf.output(pdf_filename) | |
| return pdf_filename | |
| def calculate_risk(value, thresholds, weights): | |
| """Assigns a risk weight based on threshold conditions.""" | |
| for threshold, weight in zip(thresholds, weights): | |
| if value <= threshold: | |
| return weight | |
| return weights[-1] | |
| def predict_dropout(**kwargs): | |
| """Predicts dropout risk based on multiple risk factors.""" | |
| risk_factors = [ | |
| calculate_risk(1 if kwargs.get("special_lab") == "Non-Active" else 0, [0, 1], [-0.1, 0.5]), | |
| calculate_risk(kwargs.get("attendance_percentage", 0), [50, 65, 75, 85], [1.0, 0.7, 0.2, -0.2]), | |
| calculate_risk(kwargs.get("formative_assessment", 0), [30, 50, 70, 85], [1.0, 0.7, 0.4, -0.2]), | |
| calculate_risk(kwargs.get("cgpa", 0), [5.0, 6.0, 7.0, 8.5], [1.0, 0.7, 0.4, -0.2]), | |
| calculate_risk(kwargs.get("current_sgpa", 0), [5.0, 6.0, 7.0, 8.5], [1.0, 0.7, 0.4, -0.2]), | |
| calculate_risk(kwargs.get("arrear_count", 0), [1, 3, 6, 10], [0.6, 0.8, 1.0, 1.3]), | |
| calculate_risk(kwargs.get("full_stack_rank", 0), [300, 800, 1200, 1600], [-0.3, -0.1, 0.3, 0.6]), | |
| calculate_risk(kwargs.get("ps_rank", 0), [1, 2, 4, 6], [0.8, 0.6, -0.1, -0.2]), | |
| calculate_risk(kwargs.get("Overall_Skills_Acquired", 0), [1, 4, 8, 12], [0.8, 0.5, -0.1, -0.2]), | |
| calculate_risk(kwargs.get("placement_fa", 0), [40, 60, 80, 95], [1.0, 0.7, -0.1, -0.2]), | |
| calculate_risk(kwargs.get("interim_assessment_status", 0), [50, 70, 85, 95], [1.0, 0.7, -0.1, -0.2]), | |
| calculate_risk(kwargs.get("training_assessment_status", 0), [50, 70, 85, 95], [1.0, 0.7, -0.1, -0.2]), | |
| calculate_risk(kwargs.get("mock_assessment_status", 0), [30, 50, 70, 85], [1.0, 0.7, 0.3, -0.2]), | |
| calculate_risk(kwargs.get("placement_cumulative", 0), [50, 70, 85, 95], [1.0, 0.7, -0.1, -0.2]), | |
| calculate_risk(kwargs.get("placement_Attendence", 0), [50, 70, 85, 95], [1.0, 0.7, -0.1, -0.2]), | |
| *(calculate_risk(kwargs.get(activity, 0), [0, 1, 3], [0.1, -0.2, -0.4]) for activity in [ | |
| "Technical_Competition", "Paper_Presentation", "Project_Competition", | |
| "Product_Development", "Patent", "Internship", "Online_Course" | |
| ]) | |
| ] | |
| print(risk_factors) | |
| total_risk = min(10, max(0, sum(risk_factors))) | |
| return total_risk, risk_factors | |
| def generate_plot(dropout_risk): | |
| """Creates a bar plot for dropout risk.""" | |
| fig, ax = plt.subplots() | |
| colors = ['green', 'lightgreen', 'yellow', 'orange', 'red'] | |
| labels = ['Very Low Risk', 'Low Risk', 'Moderate Risk', 'High Risk', 'Very High Risk'] | |
| index = min(int(dropout_risk // 2), 4) | |
| ax.bar([labels[index]], [dropout_risk], color=colors[index]) | |
| ax.set_ylim(0, 10) | |
| ax.set_ylabel('Dropout Risk Score') | |
| ax.set_title('Dropout Risk Prediction') | |
| plt.savefig("dropout_plot.png") # Save before using in PDF | |
| return fig ,labels[index] | |
| def remove_emojis(text): | |
| """Removes all emojis and unsupported Unicode characters from text.""" | |
| emoji_pattern = re.compile("[\U00010000-\U0010ffff]", flags=re.UNICODE) | |
| return emoji_pattern.sub("", text) | |
| def process_and_generate_report(**input_values): | |
| """Processes input values and generates risk prediction along with a report.""" | |
| dropout_risk,risk_factor = predict_dropout(**input_values) | |
| fig, label = generate_plot(dropout_risk) | |
| insights = generate_dropout_insights(input_values,risk_factor,label) | |
| cleaned_insights = remove_emojis(insights) | |
| pdf_filename = generate_pdf(input_values, dropout_risk, cleaned_insights) | |
| return fig, insights, pdf_filename |