musawar32ali commited on
Commit
6bd2916
·
verified ·
1 Parent(s): 915e578

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -363
app.py CHANGED
@@ -1,378 +1,161 @@
1
- """
2
- Automatic Time Table Generation Agent (Improved)
3
- Professional Gradio app for Hugging Face Spaces.
4
-
5
- Features:
6
- - Multi-class timetable (e.g. 1,2,3,4,5)
7
- - Teacher names (cycles if fewer than subjects)
8
- - Sunday is holiday automatically
9
- - Export to PDF, DOCX, or TXT (downloadable)
10
- - Language options: English, Sindhi, Urdu (UI + headings)
11
- - Clean, professional PDF styling
12
- """
13
-
14
- import io
15
- import os
16
- import random
17
- import tempfile
18
- from typing import Dict, List, Tuple
19
-
20
  import gradio as gr
21
- from fpdf import FPDF
22
  from docx import Document
 
 
 
 
 
23
 
24
- # ---------------------------
25
- # Localization
26
- # ---------------------------
27
- LANG_MAP = {
28
- "English": {
29
- "title": "Automatic Time Table Generation (Improved)",
30
- "subtitle": "Unique, professional timetables — Sunday is holiday by default.",
31
- "days_label": "Days (comma-separated; omit Sunday; Sunday will be shown as holiday)",
32
- "subjects_label": "Subjects (comma-separated)",
33
- "teachers_label": "Teachers (comma-separated) — will cycle if fewer than subjects",
34
- "classes_label": "Class list (comma-separated, e.g. 1,2,3,4,5)",
35
- "start_hour": "Start hour (24h)",
36
- "slot_duration": "Slot duration (hours)",
37
- "slots_per_day": "Slots per day (0 = use subjects count)",
38
- "export_format": "Export format",
39
- "generate_btn": "Generate & Export",
40
- "preview_title": "Preview (read-only)",
41
- "holiday_text": "Holiday",
42
- "time_col": "Time",
43
- "subject_col": "Subject",
44
- "teacher_col": "Teacher",
45
- "download_label": "Download file"
46
- },
47
- "Sindhi": {
48
- "title": "ٽائيم ٽيبل جنريٽر (بهتر ٿيل)",
49
- "subtitle": "منفرد ۽ پيشه ور ٽائيم ٽيبل — آچر موڪت جو ڏينھن آهي.",
50
- "days_label": "ڏينھن (ڪاما سان الڳ ڪريو، آچر پاڻ شامل ڪيو ويندو)",
51
- "subjects_label": "مضمون (ڪاما سان الڳ ڪريو)",
52
- "teachers_label": "استادن جا نالا (ڪاما سان) — مضمونن کان گهٽ هجن ته ورجايا ويندا",
53
- "classes_label": "ڪلاس لسٽ (ڪاما سان، مثال: 1,2,3,4,5)",
54
- "start_hour": "شروعاتي ڪلاڪ (24h)",
55
- "slot_duration": "هر سيشن جو دورانيون (ڪلاڪ)",
56
- "slots_per_day": "في روز سيشن (0 = مضمونن جي ڳڻپ استعمال)",
57
- "export_format": "برآمد جو فارميٽ",
58
- "generate_btn": "تيار ڪريو ۽ برآمد ڪريو",
59
- "preview_title": "پريوئو (صرف پڙهڻ)",
60
- "holiday_text": "موڪلون",
61
- "time_col": "وقت",
62
- "subject_col": "مضمون",
63
- "teacher_col": "استاد",
64
- "download_label": "فائل ڊائونلوڊ ڪريو"
65
- },
66
- "Urdu": {
67
- "title": "خودکار وقتِ جدول جنریٹر (بہتر شدہ)",
68
- "subtitle": "منفرد، پیشہ ورانہ جدول — اتوار تعطیل ہے۔",
69
- "days_label": "دن (کاما سے جدا کریں، اتوار خود شامل کیا جائے گا)",
70
- "subjects_label": "مضامین (کاما سے جدا کریں)",
71
- "teachers_label": "اساتذہ (کاما سے جدا کریں) — تعداد کم ہو تو دہرائے جائیں گے",
72
- "classes_label": "کلاس فہرست (مثال: 1,2,3,4,5)",
73
- "start_hour": "شروعات کا وقت (24h)",
74
- "slot_duration": "سیشن کا دورانیہ (گھنٹے)",
75
- "slots_per_day": "روزانہ سیٹس (0 = مضامین کی گنتی)",
76
- "export_format": "ایکسپورٹ فارمیٹ",
77
- "generate_btn": "جنریٹ اور ایکسپورٹ کریں",
78
- "preview_title": "پریویو (صرف پڑھیں)",
79
- "holiday_text": "چھٹی",
80
- "time_col": "وقت",
81
- "subject_col": "مضمون",
82
- "teacher_col": "استاد",
83
- "download_label": "فائل ڈاؤن لوڈ کریں"
84
- },
85
- }
86
-
87
- HOLIDAY = "Sunday"
88
-
89
- # ---------------------------
90
- # Core functions
91
- # ---------------------------
92
- def parse_csv_list(s: str) -> List[str]:
93
- return [p.strip() for p in s.split(",") if p.strip()]
94
-
95
- def ensure_days(days: List[str]) -> List[str]:
96
- # normalize and ensure Sunday is included at end
97
- norm = [d.strip().capitalize() for d in days if d and d.strip()]
98
- # remove duplicates preserving order
99
- seen = set()
100
- ordered = []
101
- for d in norm:
102
- if d.lower() not in seen:
103
- seen.add(d.lower())
104
- ordered.append(d)
105
- # remove any 'Sunday' if present and re-add at end
106
- ordered = [d for d in ordered if d.lower() != HOLIDAY.lower()]
107
- ordered.append(HOLIDAY)
108
- return ordered
109
-
110
- def build_teacher_map(subjects: List[str], teachers: List[str]) -> Dict[str, str]:
111
- if not teachers:
112
- return {subj: "TBD" for subj in subjects}
113
- return {subj: teachers[i % len(teachers)] for i, subj in enumerate(subjects)}
114
-
115
- def generate_timetable_for_class(
116
- days: List[str],
117
- subjects: List[str],
118
- teachers: List[str],
119
- start_hour: int = 8,
120
- slot_duration: int = 1,
121
- slots_per_day: int = 0
122
- ) -> Dict[str, List[Dict[str,str]]]:
123
- if slots_per_day <= 0:
124
- slots_per_day = len(subjects) if subjects else 0
125
-
126
- teacher_map = build_teacher_map(subjects, teachers)
127
  timetable = {}
128
- for day in days:
129
- if day.lower() == HOLIDAY.lower():
130
- timetable[day] = [] # holiday
131
- continue
132
-
133
- order = subjects.copy()
134
- random.shuffle(order)
135
- day_slots = []
136
- for i in range(slots_per_day):
137
- subj = order[i % len(order)] if order else "Free"
138
- teacher = teacher_map.get(subj, "TBD")
139
- start = (start_hour + i * slot_duration) % 24
140
- end = (start_hour + (i + 1) * slot_duration) % 24
141
- time_str = f"{start:02d}:00 - {end:02d}:00"
142
- day_slots.append({"time": time_str, "subject": subj, "teacher": teacher})
143
- timetable[day] = day_slots
144
  return timetable
145
 
146
- def generate_full_timetable(
147
- class_list: List[str],
148
- days: List[str],
149
- subjects: List[str],
150
- teachers: List[str],
151
- start_hour: int,
152
- slot_duration: int,
153
- slots_per_day: int
154
- ) -> Dict[str, Dict]:
155
- return {cls: generate_timetable_for_class(days, subjects, teachers, start_hour, slot_duration, slots_per_day) for cls in class_list}
156
-
157
- # ---------------------------
158
- # Export helpers (create temp files and return path)
159
- # ---------------------------
160
- def export_pdf_file(full_tt: Dict[str, Dict], labels: Dict[str, str]) -> str:
161
- pdf = FPDF(orientation="P", unit="mm", format="A4")
162
- pdf.set_auto_page_break(auto=True, margin=12)
163
- pdf.add_page()
164
-
165
- # Title
166
- pdf.set_font("Helvetica", "B", 18)
167
- pdf.cell(0, 10, labels["title"], ln=True, align="C")
168
- pdf.ln(2)
169
- pdf.set_font("Helvetica", "", 11)
170
- pdf.multi_cell(0, 6, labels["subtitle"])
171
- pdf.ln(6)
172
-
173
- for cls, tt in full_tt.items():
174
- pdf.set_font("Helvetica", "B", 14)
175
- pdf.cell(0, 8, f"Class {cls}", ln=True)
176
- pdf.ln(1)
177
-
178
- # table header
179
- pdf.set_font("Helvetica", "B", 11)
180
- w_time, w_subj, w_teacher = 35, 80, 60
181
- pdf.cell(w_time, 8, labels["time_col"], border=1)
182
- pdf.cell(w_subj, 8, labels["subject_col"], border=1)
183
- pdf.cell(w_teacher, 8, labels["teacher_col"], border=1)
184
- pdf.ln(8)
185
-
186
- pdf.set_font("Helvetica", "", 10)
187
- for day, slots in tt.items():
188
- pdf.set_font("Helvetica", "B", 11)
189
- pdf.cell(0, 7, f"{day}", ln=True)
190
- pdf.set_font("Helvetica", "", 10)
191
- if not slots:
192
- pdf.cell(0, 7, f" {labels['holiday_text']}", ln=True)
193
- else:
194
- for s in slots:
195
- pdf.cell(w_time, 7, s["time"], border=1)
196
- # subject cell may be long; use multi_cell trick within table by moving cursor
197
- x_before = pdf.get_x()
198
- y_before = pdf.get_y()
199
- pdf.multi_cell(w_subj, 7, s["subject"], border=1)
200
- # after multicell, set cursor for teacher column: move to right of time+subject
201
- pdf.set_xy(x_before + w_subj, y_before)
202
- pdf.cell(w_teacher, 7, s["teacher"], border=1)
203
- pdf.ln(7)
204
- pdf.ln(1)
205
- pdf.ln(6)
206
-
207
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
208
- pdf.output(tmp.name)
209
- tmp.close()
210
- return tmp.name
211
-
212
- def export_docx_file(full_tt: Dict[str, Dict], labels: Dict[str,str]) -> str:
213
  doc = Document()
214
- doc.add_heading(labels["title"], level=0)
215
- doc.add_paragraph(labels["subtitle"])
216
-
217
- for cls, tt in full_tt.items():
218
- doc.add_heading(f"Class {cls}", level=1)
219
- for day, slots in tt.items():
220
- doc.add_heading(day, level=2)
221
- if not slots:
222
- doc.add_paragraph(labels["holiday_text"])
223
- else:
224
- table = doc.add_table(rows=1, cols=3)
225
- hdr = table.rows[0].cells
226
- hdr[0].text = labels["time_col"]
227
- hdr[1].text = labels["subject_col"]
228
- hdr[2].text = labels["teacher_col"]
229
- for s in slots:
230
- row = table.add_row().cells
231
- row[0].text = s["time"]
232
- row[1].text = s["subject"]
233
- row[2].text = s["teacher"]
234
- doc.add_paragraph("")
235
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".docx")
236
- doc.save(tmp.name)
237
- tmp.close()
238
- return tmp.name
239
-
240
- def export_text_file(full_tt: Dict[str, Dict], labels: Dict[str,str]) -> str:
241
- lines = []
242
- for cls, tt in full_tt.items():
243
- lines.append(f"Class {cls}")
244
- lines.append("-" * (8 + len(str(cls))))
245
- for day, slots in tt.items():
246
- lines.append(f"{day}:")
247
- if not slots:
248
- lines.append(f" {labels['holiday_text']}")
249
- else:
250
- for s in slots:
251
- lines.append(f" {s['time']} | {s['subject']} (Teacher: {s['teacher']})")
252
- lines.append("")
253
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8")
254
- tmp.write("\n".join(lines))
255
- tmp.close()
256
- return tmp.name
257
-
258
- # ---------------------------
259
- # Main handler for Gradio
260
- # ---------------------------
261
- def build_and_export(
262
- language: str,
263
- days_input: str,
264
- subjects_input: str,
265
- teachers_input: str,
266
- classes_input: str,
267
- start_hour: int,
268
- slot_duration: int,
269
- slots_per_day: int,
270
- export_format: str
271
- ) -> Tuple[str, object]:
272
- labels = LANG_MAP.get(language, LANG_MAP["English"])
273
-
274
- days = parse_csv_list(days_input)
275
- days = ensure_days(days)
276
- subjects = [s.title() for s in parse_csv_list(subjects_input)]
277
- teachers = [t.title() for t in parse_csv_list(teachers_input)]
278
- class_list = parse_csv_list(classes_input)
279
-
280
- if not days or not subjects or not class_list:
281
- return ("Please enter Days, Subjects and Class list (comma-separated).", None)
282
-
283
- full_tt = generate_full_timetable(class_list, days, subjects, teachers, start_hour, slot_duration, slots_per_day)
284
-
285
- # Prepare preview text
286
- lines = []
287
- for cls, tt in full_tt.items():
288
- lines.append(f"Class {cls}")
289
- lines.append("-" * (8 + len(str(cls))))
290
- for day, slots in tt.items():
291
- lines.append(f"{day}:")
292
- if not slots:
293
- lines.append(f" {labels['holiday_text']}")
294
- else:
295
- for s in slots:
296
- lines.append(f" {s['time']} | {s['subject']} (Teacher: {s['teacher']})")
297
- lines.append("")
298
- preview_text = "\n".join(lines)
299
-
300
- # Export file and return a path that Gradio can present as a File
301
- if export_format == "PDF":
302
- file_path = export_pdf_file(full_tt, labels)
303
- elif export_format == "Word":
304
- file_path = export_docx_file(full_tt, labels)
305
- elif export_format == "Text":
306
- file_path = export_text_file(full_tt, labels)
307
- else:
308
- file_path = None
309
-
310
- return preview_text, file_path
311
-
312
- # ---------------------------
313
- # Gradio UI definition
314
- # ---------------------------
315
- css = """
316
- .gradio-container { max-width: 1100px; margin: auto; font-family: Arial, Helvetica, sans-serif; }
317
- .header-title { font-weight: 700; margin-left: 12px; }
318
- """
319
-
320
- with gr.Blocks(title="Automatic Time Table Generation (Improved)", css=css) as demo:
321
  with gr.Row():
322
- language = gr.Dropdown(list(LANG_MAP.keys()), value="English", label="Language / ٻولي / زبان")
323
- gr.Markdown("<h2 class='header-title'>Automatic Time Table Generation Agent (Improved)</h2>")
324
 
325
  with gr.Row():
326
- with gr.Column(scale=2):
327
- days_input = gr.Textbox(label=LANG_MAP["English"]["days_label"], value="Monday, Tuesday, Wednesday, Thursday, Friday, Saturday")
328
- subjects_input = gr.Textbox(label=LANG_MAP["English"]["subjects_label"], value="Math, English, Science, History, Art")
329
- teachers_input = gr.Textbox(label=LANG_MAP["English"]["teachers_label"], value="Mr. Khan, Ms. Ali, Mr. Iqbal")
330
- classes_input = gr.Textbox(label=LANG_MAP["English"]["classes_label"], value="1,2,3,4,5")
331
-
332
- with gr.Row():
333
- start_hour = gr.Slider(6, 10, value=8, step=1, label=LANG_MAP["English"]["start_hour"])
334
- slot_duration = gr.Slider(1, 3, value=1, step=1, label=LANG_MAP["English"]["slot_duration"])
335
-
336
- slots_per_day = gr.Number(label=LANG_MAP["English"]["slots_per_day"], value=0)
337
- export_format = gr.Dropdown(["None", "PDF", "Word", "Text"], value="PDF", label=LANG_MAP["English"]["export_format"])
338
- generate_btn = gr.Button(LANG_MAP["English"]["generate_btn"], variant="primary")
339
-
340
- with gr.Column(scale=1):
341
- preview = gr.Textbox(label=LANG_MAP["English"]["preview_title"], lines=20, interactive=False)
342
- download = gr.File(label=LANG_MAP["English"]["download_label"])
343
-
344
- # Update labels when language changes
345
- def update_labels(selected_lang):
346
- labels = LANG_MAP.get(selected_lang, LANG_MAP["English"])
347
- return (
348
- gr.update(label=labels["days_label"]),
349
- gr.update(label=labels["subjects_label"]),
350
- gr.update(label=labels["teachers_label"]),
351
- gr.update(label=labels["classes_label"]),
352
- gr.update(label=labels["start_hour"]),
353
- gr.update(label=labels["slot_duration"]),
354
- gr.update(label=labels["slots_per_day"]),
355
- gr.update(label=labels["export_format"]),
356
- gr.update(value=labels["generate_btn"]),
357
- gr.update(label=labels["download_label"]),
358
- gr.update(label=labels["preview_title"])
359
- )
360
-
361
- language.change(
362
- fn=update_labels,
363
- inputs=[language],
364
- outputs=[
365
- days_input, subjects_input, teachers_input, classes_input,
366
- start_hour, slot_duration, slots_per_day, export_format, generate_btn,
367
- download, preview
368
- ],
369
- )
370
 
371
  generate_btn.click(
372
- fn=build_and_export,
373
- inputs=[language, days_input, subjects_input, teachers_input, classes_input, start_hour, slot_duration, slots_per_day, export_format],
374
- outputs=[preview, download]
375
  )
376
 
377
  if __name__ == "__main__":
378
- demo.launch(server_name="0.0.0.0", share=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
 
2
  from docx import Document
3
+ from openpyxl import Workbook
4
+ from pptx import Presentation
5
+ from pptx.util import Inches, Pt
6
+ import tempfile
7
+ import random
8
 
9
+ # --------------------------------------------------
10
+ # Helper Functions
11
+ # --------------------------------------------------
12
+
13
+ def generate_timetable(days, subjects, teachers, classes):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  timetable = {}
15
+ for cls in classes:
16
+ class_timetable = {}
17
+ for day in days:
18
+ if day.lower() == "sunday":
19
+ class_timetable[day] = ["Holiday"]
20
+ continue
21
+ daily_subjects = random.sample(subjects, len(subjects))
22
+ daily_teachers = random.sample(teachers, len(teachers))
23
+ class_timetable[day] = [f"{subj} — {teacher}" for subj, teacher in zip(daily_subjects, daily_teachers)]
24
+ timetable[cls] = class_timetable
 
 
 
 
 
 
25
  return timetable
26
 
27
+
28
+ def format_timetable_text(timetable):
29
+ output = ""
30
+ for cls, schedule in timetable.items():
31
+ output += f"\n===== Class {cls} =====\n"
32
+ for day, entries in schedule.items():
33
+ output += f"{day}:\n"
34
+ for entry in entries:
35
+ output += f" - {entry}\n"
36
+ output += "\n"
37
+ return output
38
+
39
+
40
+ # --------------------------------------------------
41
+ # File Export Functions
42
+ # --------------------------------------------------
43
+
44
+ def save_to_word(text):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  doc = Document()
46
+ doc.add_heading("Automatic Timetable", level=1)
47
+ doc.add_paragraph(text)
48
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=".docx")
49
+ doc.save(temp.name)
50
+ return temp.name
51
+
52
+
53
+ def save_to_text(text):
54
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=".txt")
55
+ with open(temp.name, "w", encoding="utf-8") as f:
56
+ f.write(text)
57
+ return temp.name
58
+
59
+
60
+ def save_to_excel(timetable):
61
+ wb = Workbook()
62
+ ws = wb.active
63
+ ws.title = "Timetable"
64
+
65
+ ws.append(["Class", "Day", "Schedule"])
66
+
67
+ for cls, schedule in timetable.items():
68
+ for day, entries in schedule.items():
69
+ ws.append([cls, day, ", ".join(entries)])
70
+
71
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx")
72
+ wb.save(temp.name)
73
+ return temp.name
74
+
75
+
76
+ def save_to_ppt(timetable):
77
+ prs = Presentation()
78
+ title_slide_layout = prs.slide_layouts[1]
79
+
80
+ for cls, schedule in timetable.items():
81
+ slide = prs.slides.add_slide(title_slide_layout)
82
+ title = slide.shapes.title
83
+ body = slide.placeholders[1]
84
+
85
+ title.text = f"Class {cls} Timetable"
86
+ text_frame = body.text_frame
87
+
88
+ for day, entries in schedule.items():
89
+ text_frame.add_paragraph().text = f"{day}: {', '.join(entries)}"
90
+
91
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=".pptx")
92
+ prs.save(temp.name)
93
+ return temp.name
94
+
95
+
96
+
97
+ # --------------------------------------------------
98
+ # Main Function
99
+ # --------------------------------------------------
100
+
101
+ def generate(days_input, subjects_input, teachers_input, classes_input, language):
102
+ days = [d.strip().capitalize() for d in days_input.split(",") if d.strip()]
103
+ subjects = [s.strip().capitalize() for s in subjects_input.split(",") if s.strip()]
104
+ teachers = [t.strip().capitalize() for t in teachers_input.split(",") if t.strip()]
105
+ classes = [c.strip() for c in classes_input.split(",") if c.strip()]
106
+
107
+ if not days or not subjects or not teachers or not classes:
108
+ return "⚠️ Please fill all fields.", None, None, None, None
109
+
110
+ timetable = generate_timetable(days, subjects, teachers, classes)
111
+ text_output = format_timetable_text(timetable)
112
+
113
+ # Save files
114
+ doc_file = save_to_word(text_output)
115
+ txt_file = save_to_text(text_output)
116
+ excel_file = save_to_excel(timetable)
117
+ ppt_file = save_to_ppt(timetable)
118
+
119
+ return text_output, doc_file, txt_file, excel_file, ppt_file
120
+
121
+
122
+
123
+ # --------------------------------------------------
124
+ # Gradio UI
125
+ # --------------------------------------------------
126
+
127
+ with gr.Blocks(theme=gr.themes.Soft(), title="Automatic Time Table Generator (Improved)") as demo:
128
+ gr.Markdown("""
129
+ # 🗓️ Automatic Time Table Generation Agent (Improved)
130
+ **Generate easy, unique, and stylish timetables**
131
+ Export to **Word, Excel, PowerPoint, and Text**
132
+ Includes multi-language option, teacher names, class list, and Sunday holiday.
133
+ """)
134
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  with gr.Row():
136
+ language = gr.Dropdown(["English", "Sindhi", "Urdu", "Other"], label="Select Language", value="English")
 
137
 
138
  with gr.Row():
139
+ days_input = gr.Textbox(label="Days (comma-separated)",
140
+ value="Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday")
141
+ classes_input = gr.Textbox(label="Class List", value="1, 2, 3, 4, 5")
142
+
143
+ subjects_input = gr.Textbox(label="Subjects", value="Math, English, Science, History, Art")
144
+ teachers_input = gr.Textbox(label="Teacher Names", value="Mr. Ali, Ms. Fatima, Mr. Khan, Ms. Sara, Mr. Ahmed")
145
+
146
+ generate_btn = gr.Button("✨ Generate Timetable")
147
+
148
+ output_text = gr.Textbox(label="Generated Timetable", lines=15)
149
+ doc_output = gr.File(label="📝 Download Word (.docx)")
150
+ txt_output = gr.File(label="📃 Download Text (.txt)")
151
+ excel_output = gr.File(label="📊 Download Excel (.xlsx)")
152
+ ppt_output = gr.File(label="📽️ Download PowerPoint (.pptx)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  generate_btn.click(
155
+ fn=generate,
156
+ inputs=[days_input, subjects_input, teachers_input, classes_input, language],
157
+ outputs=[output_text, doc_output, txt_output, excel_output, ppt_output]
158
  )
159
 
160
  if __name__ == "__main__":
161
+ demo.launch(server_name="0.0.0.0", share=True)