succesfull testing
This commit is contained in:
59
controller/solver/phase1_general.py
Normal file
59
controller/solver/phase1_general.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Phase 1: general courses (shared across every batch of a session).
|
||||
|
||||
Simple strategy — small offering count, Tue/Thu preferred first. After
|
||||
placing everything, self-repair: any batch left with two general-course
|
||||
sessions in the same slot has the losing session unmarked and re-placed
|
||||
(scanning every day) until this phase's own sessions are clash-free.
|
||||
"""
|
||||
|
||||
from . import grid
|
||||
|
||||
|
||||
def run(board, data, preferred_days=("Tuesday", "Thursday"), max_repair_attempts=20):
|
||||
"""Places every general-course offering's weekly lectures. Returns this phase's sessions."""
|
||||
general = [o for o in data["offerings"] if o["course"]["is_general"]]
|
||||
preferred_order = list(preferred_days) + [d for d in grid.DAYS if d not in preferred_days]
|
||||
phase_start = len(board.sessions)
|
||||
|
||||
for offering in general:
|
||||
course = offering["course"]
|
||||
room_candidates = board.room_candidates(course["lecture_room_id"], board.classrooms)
|
||||
for _ in range(course["lectures_per_week"]):
|
||||
session = board.place_lecture(offering, room_candidates, preferred_order)
|
||||
if session is None:
|
||||
print(f"WARNING: could not place a lecture for general course {offering['course_id']} section {offering['section_id']}")
|
||||
|
||||
phase_sessions = board.sessions[phase_start:]
|
||||
_repair_general_conflicts(board, data, phase_sessions, max_repair_attempts)
|
||||
return phase_sessions
|
||||
|
||||
|
||||
def _repair_general_conflicts(board, data, phase_sessions, max_attempts):
|
||||
"""Moves general-course sessions that clash for a batch to a free slot on any day."""
|
||||
from conflict_checker.student_conflict_checker import check_student_conflicts
|
||||
|
||||
any_day_order = list(grid.DAYS)
|
||||
for _ in range(max_attempts):
|
||||
conflicts = check_student_conflicts(phase_sessions)
|
||||
if not conflicts:
|
||||
return
|
||||
|
||||
# Re-place the last session involved in the first conflict; the
|
||||
# other session(s) in that cell stay put.
|
||||
losing_session = conflicts[0]["sessions"][-1]
|
||||
offering = next(
|
||||
o for o in data["offerings"]
|
||||
if o["course_id"] == losing_session["course_id"] and o["section_id"] == losing_session["section_id"]
|
||||
)
|
||||
board.remove_session(losing_session)
|
||||
phase_sessions.remove(losing_session)
|
||||
|
||||
room_candidates = board.room_candidates(offering["course"]["lecture_room_id"], board.classrooms)
|
||||
new_session = board.place_lecture(offering, room_candidates, any_day_order)
|
||||
if new_session is None:
|
||||
print(f"WARNING: could not repair general-course conflict for {offering['course_id']} section {offering['section_id']}")
|
||||
return
|
||||
phase_sessions.append(new_session)
|
||||
|
||||
print("WARNING: general-course conflicts remained unresolved after max repair attempts")
|
||||
Reference in New Issue
Block a user