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