Spaces:
Paused
Paused
| import gradio as gr | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| from math import ceil | |
| from reportlab.platypus import SimpleDocTemplate, Table, TableStyle | |
| from reportlab.lib import colors | |
| import tempfile | |
| # --- Core Planner Logic --- | |
| class Subject: | |
| def __init__(self, name, lectures_per_day, backlog, avg_time, priority): | |
| self.name = name | |
| self.A = lectures_per_day | |
| self.B = backlog | |
| self.time = avg_time | |
| self.priority = priority | |
| class Planner: | |
| def __init__(self, subjects, avg_hours, max_hours): | |
| self.subjects = subjects | |
| self.avg_minutes = avg_hours * 60 | |
| self.max_minutes = max_hours * 60 | |
| def calculate(self, T): | |
| daily_plan = {} | |
| total_time = 0 | |
| for s in self.subjects: | |
| required = s.A + ceil((s.B * s.priority) / T) | |
| time_needed = required * s.time | |
| daily_plan[s.name] = {"lectures": required, "time": time_needed} | |
| total_time += time_needed | |
| return daily_plan, total_time | |
| def auto_adjust_days(self, T): | |
| while True: | |
| plan, time = self.calculate(T) | |
| if time <= self.avg_minutes: | |
| return T, plan, time | |
| T += 1 | |
| # --- Gradio Functions --- | |
| def run_planner(df_input, target_days, avg_hours, max_hours): | |
| # Convert dataframe to Subject list | |
| subjects = [] | |
| for _, row in df_input.iterrows(): | |
| try: | |
| subjects.append(Subject( | |
| str(row["Subject"]), | |
| float(row["Lectures/day"]), | |
| int(row["Backlog"]), | |
| float(row["Avg time"]), | |
| float(row["Priority"]) | |
| )) | |
| except: | |
| continue | |
| planner = Planner(subjects, float(avg_hours), float(max_hours)) | |
| T, plan, total_time = planner.auto_adjust_days(int(target_days)) | |
| # Build dataframe output | |
| df_output = pd.DataFrame([ | |
| [k, v["lectures"], round(v["time"],1)] | |
| for k, v in plan.items() | |
| ], columns=["Subject","Lectures/day","Time/day (min)"]) | |
| # Text summary | |
| summary = f"Adjusted target days: {T}\nTotal daily time: {total_time:.1f} min\n\n" | |
| for k, v in plan.items(): | |
| summary += f"{k}: {v['lectures']} lectures → {v['time']:.1f} min/day\n" | |
| return df_output, summary | |
| def plot_graph(df_output): | |
| fig, ax = plt.subplots(figsize=(6,4)) | |
| ax.pie(df_output["Time/day (min)"], labels=df_output["Subject"], autopct='%1.1f%%') | |
| ax.set_title("Daily Time Distribution") | |
| tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png") | |
| plt.savefig(tmp_file.name) | |
| plt.close(fig) | |
| return tmp_file.name | |
| def export_csv(df_output): | |
| tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".csv") | |
| df_output.to_csv(tmp_file.name, index=False) | |
| return tmp_file.name | |
| def export_pdf(df_output): | |
| tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") | |
| doc = SimpleDocTemplate(tmp_file.name) | |
| data = [df_output.columns.tolist()] + df_output.values.tolist() | |
| table = Table(data) | |
| style = TableStyle([ | |
| ('BACKGROUND',(0,0),(-1,0),colors.grey), | |
| ('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke), | |
| ('ALIGN',(0,0),(-1,-1),'CENTER'), | |
| ('GRID',(0,0),(-1,-1),1,colors.black), | |
| ]) | |
| table.setStyle(style) | |
| doc.build([table]) | |
| return tmp_file.name | |
| # --- Gradio Interface --- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 📝 Advanced Backlog Planner") | |
| with gr.Row(): | |
| with gr.Column(): | |
| df_input = gr.Dataframe( | |
| headers=["Subject","Lectures/day","Backlog","Avg time","Priority"], | |
| datatype=["str","number","number","number","number"], | |
| interactive=True, | |
| label="Subjects Input" | |
| ) | |
| target_days = gr.Number(label="Target Days", value=5) | |
| avg_hours = gr.Number(label="Avg hrs/day", value=4) | |
| max_hours = gr.Number(label="Max hrs/day", value=8) | |
| run_button = gr.Button("Calculate Plan") | |
| with gr.Column(): | |
| summary_output = gr.Textbox(label="Summary", lines=15) | |
| table_output = gr.Dataframe(headers=["Subject","Lectures/day","Time/day (min)"]) | |
| graph_output = gr.Image(label="Graph") | |
| csv_output = gr.File(label="Download CSV") | |
| pdf_output = gr.File(label="Download PDF") | |
| def compute(df_input, target_days, avg_hours, max_hours): | |
| df_output, summary = run_planner(df_input, target_days, avg_hours, max_hours) | |
| return df_output, summary | |
| run_button.click( | |
| compute, | |
| inputs=[df_input, target_days, avg_hours, max_hours], | |
| outputs=[table_output, summary_output] | |
| ) | |
| # Graph button | |
| gr.Button("Show Graph").click(plot_graph, inputs=[table_output], outputs=[graph_output]) | |
| # CSV button | |
| gr.Button("Export CSV").click(export_csv, inputs=[table_output], outputs=[csv_output]) | |
| # PDF button | |
| gr.Button("Export PDF").click(export_pdf, inputs=[table_output], outputs=[pdf_output]) | |
| demo.launch() | |