Spaces:
Sleeping
Sleeping
Update timetable.py
Browse files- timetable.py +62 -37
timetable.py
CHANGED
|
@@ -1,56 +1,81 @@
|
|
| 1 |
import pandas as pd
|
| 2 |
-
|
| 3 |
|
| 4 |
DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
|
|
|
|
| 5 |
|
| 6 |
-
def
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
|
| 18 |
def generate_timetable(courses_path, rooms_path):
|
| 19 |
courses = pd.read_csv(courses_path)
|
| 20 |
rooms = pd.read_csv(rooms_path)["Room"].tolist()
|
| 21 |
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
| 31 |
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
start = slots[slot_idx]
|
| 35 |
-
end = start + duration
|
| 36 |
|
| 37 |
-
|
| 38 |
-
"
|
| 39 |
-
"
|
| 40 |
-
"
|
| 41 |
-
"
|
| 42 |
-
"Room": rooms[room_idx % len(rooms)]
|
| 43 |
})
|
| 44 |
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
-
|
|
|
|
|
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
+
import random
|
| 3 |
|
| 4 |
DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
|
| 5 |
+
TIME_SLOTS = ["9:00-10:00", "10:00-11:00", "11:00-12:30", "12:30-1:30", "1:30-3:00"]
|
| 6 |
|
| 7 |
+
def split_course_hours(courses_df):
|
| 8 |
+
"""
|
| 9 |
+
Split total weekly hours into chunks of max 1.5 hours per day.
|
| 10 |
+
Returns a list of dicts with course, teacher, duration.
|
| 11 |
+
"""
|
| 12 |
+
course_blocks = []
|
| 13 |
+
for _, row in courses_df.iterrows():
|
| 14 |
+
remaining = row['Hours']
|
| 15 |
+
while remaining > 0:
|
| 16 |
+
dur = 1.5 if remaining >= 1.5 else 1.0
|
| 17 |
+
course_blocks.append({
|
| 18 |
+
"Course": row['Course'],
|
| 19 |
+
"Teacher": row['Teacher'],
|
| 20 |
+
"Duration": dur
|
| 21 |
+
})
|
| 22 |
+
remaining -= dur
|
| 23 |
+
return course_blocks
|
| 24 |
|
| 25 |
|
| 26 |
def generate_timetable(courses_path, rooms_path):
|
| 27 |
courses = pd.read_csv(courses_path)
|
| 28 |
rooms = pd.read_csv(rooms_path)["Room"].tolist()
|
| 29 |
|
| 30 |
+
course_blocks = split_course_hours(courses)
|
| 31 |
+
|
| 32 |
+
# Initialize timetable dictionary: one list per day
|
| 33 |
+
timetable = {day: [] for day in DAYS}
|
| 34 |
+
teacher_last_slot = {t: None for t in courses['Teacher'].unique()}
|
| 35 |
+
|
| 36 |
+
for day in DAYS:
|
| 37 |
+
available_slots = TIME_SLOTS.copy()
|
| 38 |
+
random.shuffle(course_blocks) # Randomize to reduce conflicts
|
| 39 |
+
day_schedule = []
|
| 40 |
|
| 41 |
+
i = 0
|
| 42 |
+
while i < len(course_blocks) and available_slots:
|
| 43 |
+
block = course_blocks[i]
|
| 44 |
+
teacher = block['Teacher']
|
| 45 |
|
| 46 |
+
# Check teacher consecutive slot
|
| 47 |
+
if teacher_last_slot[teacher] == day and available_slots:
|
| 48 |
+
i += 1
|
| 49 |
+
continue
|
| 50 |
|
| 51 |
+
slot = available_slots.pop(0)
|
| 52 |
+
room = rooms[i % len(rooms)]
|
|
|
|
|
|
|
| 53 |
|
| 54 |
+
day_schedule.append({
|
| 55 |
+
"Time": slot,
|
| 56 |
+
"Course": block['Course'],
|
| 57 |
+
"Teacher": teacher,
|
| 58 |
+
"Room": room
|
|
|
|
| 59 |
})
|
| 60 |
|
| 61 |
+
teacher_last_slot[teacher] = day
|
| 62 |
+
# Remove block from list if allocated
|
| 63 |
+
course_blocks.pop(i)
|
| 64 |
+
timetable[day] = day_schedule
|
| 65 |
|
| 66 |
+
# Convert timetable dict to printable DataFrame
|
| 67 |
+
max_columns = max(len(v) for v in timetable.values())
|
| 68 |
+
table_data = []
|
| 69 |
|
| 70 |
+
for day in DAYS:
|
| 71 |
+
row = [day]
|
| 72 |
+
for cls in timetable[day]:
|
| 73 |
+
row.append(f"{cls['Course']} ({cls['Teacher']})\n{cls['Time']}")
|
| 74 |
+
# Fill remaining columns with empty
|
| 75 |
+
while len(row) <= max_columns:
|
| 76 |
+
row.append("")
|
| 77 |
+
table_data.append(row)
|
| 78 |
|
| 79 |
+
columns = ["Day"] + [f"Slot {i+1}" for i in range(max_columns)]
|
| 80 |
+
df = pd.DataFrame(table_data, columns=columns)
|
| 81 |
+
return df
|