Spaces:
Sleeping
Sleeping
Update api.py
Browse files
api.py
CHANGED
|
@@ -244,6 +244,7 @@ class GenerateRequest(BaseModel):
|
|
| 244 |
time_limit_seconds: int = 30
|
| 245 |
version_label: Optional[str] = None
|
| 246 |
semesters: Optional[List[int]] = None # e.g. [5, 7] for odd sems only
|
|
|
|
| 247 |
|
| 248 |
class UpdateRequest(BaseModel):
|
| 249 |
prompt: str
|
|
@@ -978,37 +979,43 @@ def generate(req: GenerateRequest):
|
|
| 978 |
raise HTTPException(400, f"Missing data for: {', '.join(missing)}.")
|
| 979 |
|
| 980 |
# ββ Semester filtering ββββββββββββββββββββββββββββββββββββββββββββ
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
|
| 991 |
-
|
| 992 |
-
|
| 993 |
-
|
| 994 |
-
|
| 995 |
-
|
| 996 |
-
|
| 997 |
-
|
| 998 |
-
|
| 999 |
-
|
| 1000 |
-
|
| 1001 |
-
|
| 1002 |
-
|
| 1003 |
-
|
| 1004 |
-
|
| 1005 |
-
|
| 1006 |
-
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
|
| 1011 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1012 |
|
| 1013 |
facs, subs, secs, rooms, allocs = _build_objects(data)
|
| 1014 |
tasks = prepare_scheduling_tasks(allocs, facs, subs, secs)
|
|
@@ -1016,12 +1023,21 @@ def generate(req: GenerateRequest):
|
|
| 1016 |
if not tasks:
|
| 1017 |
raise HTTPException(400, "No schedulable tasks found. Check your allocations.")
|
| 1018 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1019 |
solver = TimetableSolver(tasks, facs, secs, rooms)
|
| 1020 |
try:
|
| 1021 |
status, solution = solver.solve(
|
| 1022 |
time_limit_seconds=req.time_limit_seconds,
|
| 1023 |
enable_soft_constraints=True,
|
| 1024 |
scheduling_rules=data.get("scheduling_rules", []),
|
|
|
|
|
|
|
| 1025 |
)
|
| 1026 |
except ValueError as e:
|
| 1027 |
raise HTTPException(status_code=400, detail=str(e))
|
|
|
|
| 244 |
time_limit_seconds: int = 30
|
| 245 |
version_label: Optional[str] = None
|
| 246 |
semesters: Optional[List[int]] = None # e.g. [5, 7] for odd sems only
|
| 247 |
+
locked_semesters: Optional[List[int]] = None
|
| 248 |
|
| 249 |
class UpdateRequest(BaseModel):
|
| 250 |
prompt: str
|
|
|
|
| 979 |
raise HTTPException(400, f"Missing data for: {', '.join(missing)}.")
|
| 980 |
|
| 981 |
# ββ Semester filtering ββββββββββββββββββββββββββββββββββββββββββββ
|
| 982 |
+
has_sems = bool(req.semesters)
|
| 983 |
+
has_locked = bool(req.locked_semesters)
|
| 984 |
+
if has_sems or has_locked:
|
| 985 |
+
selected_sems = set(req.semesters or [])
|
| 986 |
+
locked_sems = set(req.locked_semesters or [])
|
| 987 |
+
combined_sems = selected_sems.union(locked_sems)
|
| 988 |
+
|
| 989 |
+
if combined_sems:
|
| 990 |
+
# 1. Filter sections to only combined semesters
|
| 991 |
+
data["sections"] = [
|
| 992 |
+
s for s in data["sections"] if s["semester"] in combined_sems
|
| 993 |
+
]
|
| 994 |
+
if not data["sections"]:
|
| 995 |
+
raise HTTPException(400, f"No sections found for semesters: {combined_sems}")
|
| 996 |
+
|
| 997 |
+
# 2. Filter allocations to only reference surviving sections
|
| 998 |
+
valid_section_ids = {s["id"] for s in data["sections"]}
|
| 999 |
+
data["allocations"] = [
|
| 1000 |
+
a for a in data["allocations"]
|
| 1001 |
+
if a["section_id"] in valid_section_ids
|
| 1002 |
+
]
|
| 1003 |
+
|
| 1004 |
+
# 3. Filter subjects to only those referenced by surviving allocations
|
| 1005 |
+
used_subject_codes = {a["subject_code"] for a in data["allocations"]}
|
| 1006 |
+
data["subjects"] = [
|
| 1007 |
+
s for s in data["subjects"] if s["code"] in used_subject_codes
|
| 1008 |
+
]
|
| 1009 |
+
|
| 1010 |
+
# 4. Filter faculties to only those referenced by surviving allocations
|
| 1011 |
+
used_faculty_ids = {a["faculty_id"] for a in data["allocations"]}
|
| 1012 |
+
data["faculties"] = [
|
| 1013 |
+
f for f in data["faculties"] if f["id"] in used_faculty_ids
|
| 1014 |
+
]
|
| 1015 |
+
|
| 1016 |
+
print(f"[generate] Filtered to combined semesters {combined_sems}: "
|
| 1017 |
+
f"{len(data['sections'])} sections, {len(data['allocations'])} allocations, "
|
| 1018 |
+
f"{len(data['subjects'])} subjects, {len(data['faculties'])} faculties")
|
| 1019 |
|
| 1020 |
facs, subs, secs, rooms, allocs = _build_objects(data)
|
| 1021 |
tasks = prepare_scheduling_tasks(allocs, facs, subs, secs)
|
|
|
|
| 1023 |
if not tasks:
|
| 1024 |
raise HTTPException(400, "No schedulable tasks found. Check your allocations.")
|
| 1025 |
|
| 1026 |
+
locked_schedule = {}
|
| 1027 |
+
if req.locked_semesters:
|
| 1028 |
+
if schedule_exists():
|
| 1029 |
+
locked_schedule = load_schedule()
|
| 1030 |
+
else:
|
| 1031 |
+
raise HTTPException(400, "Cannot lock semesters: no existing schedule found.")
|
| 1032 |
+
|
| 1033 |
solver = TimetableSolver(tasks, facs, secs, rooms)
|
| 1034 |
try:
|
| 1035 |
status, solution = solver.solve(
|
| 1036 |
time_limit_seconds=req.time_limit_seconds,
|
| 1037 |
enable_soft_constraints=True,
|
| 1038 |
scheduling_rules=data.get("scheduling_rules", []),
|
| 1039 |
+
locked_schedule=locked_schedule,
|
| 1040 |
+
locked_semesters=req.locked_semesters
|
| 1041 |
)
|
| 1042 |
except ValueError as e:
|
| 1043 |
raise HTTPException(status_code=400, detail=str(e))
|