KindAlien commited on
Commit
46edfbd
Β·
verified Β·
1 Parent(s): a935bbc

Update api.py

Browse files
Files changed (1) hide show
  1. api.py +47 -31
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
- if req.semesters:
982
- selected_sems = set(req.semesters)
983
- # 1. Filter sections to only selected semesters
984
- data["sections"] = [
985
- s for s in data["sections"] if s["semester"] in selected_sems
986
- ]
987
- if not data["sections"]:
988
- raise HTTPException(400, f"No sections found for semesters: {req.semesters}")
989
-
990
- # 2. Filter allocations to only reference surviving sections
991
- valid_section_ids = {s["id"] for s in data["sections"]}
992
- data["allocations"] = [
993
- a for a in data["allocations"]
994
- if a["section_id"] in valid_section_ids
995
- ]
996
-
997
- # 3. Filter subjects to only those referenced by surviving allocations
998
- used_subject_codes = {a["subject_code"] for a in data["allocations"]}
999
- data["subjects"] = [
1000
- s for s in data["subjects"] if s["code"] in used_subject_codes
1001
- ]
1002
-
1003
- # 4. Filter faculties to only those referenced by surviving allocations
1004
- used_faculty_ids = {a["faculty_id"] for a in data["allocations"]}
1005
- data["faculties"] = [
1006
- f for f in data["faculties"] if f["id"] in used_faculty_ids
1007
- ]
1008
-
1009
- print(f"[generate] Filtered to semesters {req.semesters}: "
1010
- f"{len(data['sections'])} sections, {len(data['allocations'])} allocations, "
1011
- f"{len(data['subjects'])} subjects, {len(data['faculties'])} faculties")
 
 
 
 
 
 
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))