可以幫我加入這些新功能嗎?1.自动排课推荐:当学生选课冲突时,推荐其他时间段的相同课程。
2.容量预警:当课程容量使用超过90%时,标记为“即将满员”。
3.冲突高亮:在可视化课表中用红色标注冲突课程,謝謝 import csv
from collections import defaultdict
# 定义时间段区间
time_periods = {
"上午": [("8:00","10:00"),("8:00","11:00"),("10:00","12:00"),("9:00","12:00")],
"下午": [("1:00","3:00"),("1:00","4:00"),("3:00","5:00"),("2:00","5:00")]
}
def convert_time_format(time_slots):
converted_slots = []
for day, start, end in time_slots:
period = None
# 检查是否属于上午时间段
for am_start, am_end in time_periods["上午"]:
if start == am_start and end == am_end:
period = "上午"
break
# 如果不属于上午,检查是否属于下午
if not period:
for pm_start, pm_end in time_periods["下午"]:
if start == pm_start and end == pm_end:
period = "下午"
break
# 如果都不属于,默认为上午(根据需求可以调整)
if not period:
period = "上午"
converted_slots.append((day, f"{period}{start}-{end}"))
return converted_slots
# 课程类
class Course:
def __init__(self, course_ID, name, time, capacity=50, current_student=0, allowed_majors=None, prerequisites=None, classroom=""):
self.course_ID = course_ID
self.name = name
self.time = convert_time_format(time) # 转换时间格式
self.capacity = capacity
self.current_student = current_student
self.allowed_majors = allowed_majors if allowed_majors else []
self.prerequisites = prerequisites if prerequisites else []
self.classroom = classroom
def is_time_conflict(self, other_course):
for slot1 in self.time:
for slot2 in other_course.time:
if slot1[0] == slot2[0]: # 检查两个课程时间段是否同一天
# 提取时间部分(去掉上午/下午)
time1 = slot1[1][2:] if len(slot1[1]) > 5 else slot1[1] # 处理可能已经转换过的格式
time2 = slot2[1][2:] if len(slot2[1]) > 5 else slot2[1]
start1, end1 = time1.split('-')
start2, end2 = time2.split('-')
if max(start1, start2) < min(end1, end2): # 检查两个课程时间段是否重叠
return True # 如果两个时间段在同一天且有重叠,返回True
return False # 否则返回False
# 管理员类
class Admin:
def __init__(self):
self.courses = {} # 存储所有课程的字典
def add_course(self, course):
if course.course_ID in self.courses:
print(f"课程 {course.course_ID} 已存在,无法添加。")
else:
self.courses[course.course_ID] = course
print(f"您已成功添加课程{course.course_ID}。")
def add_courses_from_csv(self, file_path):
added_courses = []
skipped_courses = []
try:
with open(file_path, 'r', encoding='utf-8') as file:
reader = csv.DictReader(file)
for row in reader:
try:
course_ID = row['course_ID']
name = row['name']
time = eval(row['time']) # 假设时间以列表形式存储
capacity = int(row.get('capacity', 50))
allowed_majors = eval(row.get('allowed_majors', "[]"))
prerequisites = eval(row.get('prerequisites', "[]"))
classroom = row.get('classroom', "")
new_course = Course(course_ID, name, time, capacity, 0, allowed_majors, prerequisites, classroom)
self.add_course(new_course)
added_courses.append(course_ID)
except Exception as e:
skipped_courses.append((row.get('course_ID', '未知'), str(e)))
except FileNotFoundError:
print("文件未找到,请检查路径。")
return
print(f"您已成功添加课程:{added_courses}")
if skipped_courses:
print(f"已跳過格式错误的行:{skipped_courses}")
def update_course(self, course_ID, **kwargs):
if course_ID in self.courses:
course = self.courses[course_ID]
for key, value in kwargs.items():
if key == 'time' and isinstance(value, list):
value = convert_time_format(value) # 转换时间格式
if hasattr(course, key):
setattr(course, key, value)
print(f"课程 {course_ID} 更新成功。")
else:
print(f"课程 {course_ID} 不存在,无法更新。")
def delete_course(self, course_ID):
if course_ID in self.courses:
del self.courses[course_ID]
print(f"成功删除课程{course_ID}")
else:
print(f"课程 {course_ID}不存在,无法删除!")
# 学生类
class Student:
def __init__(self, student_id, major):
self.student_id = student_id
self.major = major
self.selected_courses = []
def select_course(self, course, admin):
if course.course_ID not in admin.courses:
print(f"选课失敗:课程 {course.course_ID} 不存在,无法选课。")
return
if course.current_student >= course.capacity:
print(f"选课失敗:课程 {course.course_ID} 学生容量已满,无法选课。")
return
if course.allowed_majors and self.major not in course.allowed_majors:
print(f"选课失敗:您的专业 {self.major}不符合课程 {course.course_ID} 的专业限制要求。")
return
missing_prereqs = [p for p in course.prerequisites if p not in [c.course_ID for c in self.selected_courses]]
if missing_prereqs:
print(f"选课失敗:您尚未完成先修课程:{missing_prereqs},因此无法选择这门课程。")
return
if any(selected_course.is_time_conflict(course) for selected_course in self.selected_courses):
conflicting_courses = [c.course_ID for c in self.selected_courses if c.is_time_conflict(course)]
print(f"选课失敗:与课程{conflicting_courses}时间冲突")
return
self.selected_courses.append(course)
course.current_student += 1
print(f"您已成功选课:{course.course_ID}{course.name}")
#
def drop_course(self, course):
if course in self.selected_courses:
self.selected_courses.remove(course)
course.current_student -= 1
print(f"您已成功退选:{course.course_ID}")
else:
print(f"您未选择课程 {course.course_ID},无法退选。")
def visualize_schedule(self):
schedule = defaultdict(list)
for course in self.selected_courses:
for day, time_slot in course.time:
schedule[day].append(f"{time_slot}: {course.name}")
print(f"== 学生 {self.student_id} 的课表 ==")
for day, slots in sorted(schedule.items()):
print(f"{day}:")
for slot in sorted(slots):
print(f" {slot}")
#
def validate_course_id(course_id):
"""校验课程ID格式"""
if not course_id or not isinstance(course_id, str):
return False, "课程ID必须是非空字符串"
return True, ""
def validate_course_name(name):
"""校验课程名称格式"""
if not name or len(name.strip()) == 0:
return False, "课程名称不能为空"
return True, ""
def validate_time_slot(time_str):
"""校验单个时间段格式"""
try:
day, period = time_str.strip().split(" ", 1)
if day not in ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]:
return False, f"无效的星期格式: {day}"
start_end = period.split("-")
if len(start_end) != 2:
return False, "时间段格式应为'开始时间-结束时间'"
start, end = start_end
start = start.strip()
end = end.strip()
# 检查时间格式
for t in [start, end]:
if ":" not in t:
return False, f"时间格式应为HH:MM: {t}"
hours, mins = map(int, t.split(":"))
if hours < 0 or hours > 23 or mins < 0 or mins > 59:
return False, f"无效的时间值: {t}"
# 检查是否为整点
if not (start.endswith(":00") and end.endswith(":00")):
return False, "时间段必须为整点开始和结束"
# 检查时间段是否符合规定
start_hour = int(start.split(":")[0])
end_hour = int(end.split(":")[0])
duration = end_hour - start_hour
if start_hour < 12: # 上午
if not ((start_hour == 8 and end_hour == 10) or # 2节课
(start_hour == 8 and end_hour == 11) or # 3节课
(start_hour == 10 and end_hour == 12) or # 2节课
(start_hour == 9 and end_hour == 12)): # 3节课
return False, "上午时间段不符合规定"
else: # 下午
if not ((start_hour == 13 and end_hour == 15) or # 2节课
(start_hour == 13 and end_hour == 16) or # 3节课
(start_hour == 15 and end_hour == 17) or # 2节课
(start_hour == 14 and end_hour == 17)): # 3节课
return False, "下午时间段不符合规定"
return True, ""
except Exception as e:
return False, f"时间格式错误: {str(e)}"
def validate_capacity(capacity_str):
"""校验课程容量"""
try:
capacity = int(capacity_str)
if capacity <= 0:
return False, "课程容量必须是正整数"
return True, ""
except ValueError:
return False, "课程容量必须是整数"
def validate_majors(majors_str):
"""校验专业列表"""
if not majors_str:
return True, ""
majors = [m.strip() for m in majors_str.split(",") if m.strip()]
if not all(m for m in majors):
return False, "专业名称不能为空"
return True, ""
def validate_prerequisites(prereqs_str, existing_courses):
"""校验先修课程"""
if not prereqs_str:
return True, ""
prereqs = [p.strip() for p in prereqs_str.split(",") if p.strip()]
for p in prereqs:
if p not in existing_courses:
return False, f"先修课程 {p} 不存在于系统中"
return True, ""
#主頁面
def main_menu():
print("\n===高校选课系统主頁面===")
print("1.管理员登录")
print("2.学生登录")
print("3.退出系统")
choice=input("请选择登录身份(1-3):")
return choice
# 管理员菜单
def admin_menu(admin):
while True:
print("\n===管理員功能頁面===")
print("1.手動添加單條课程")
print("2.批量导入课程(CSV)")
print("3.更新课程信息")
print("4.删除课程")
print("5.查看所有课程")
print("6.返回主菜单")
choice=input("请选择功能(1-6):")
if choice=="1":
# 课程ID校验
while True:
course_ID=input("请输入课程ID(唯一字符串,如CS101):")
valid, msg = validate_course_id(course_ID)
if valid and course_ID not in admin.courses:
break
if not valid:
print(f"输入错误:{msg}")
else:
print("该课程ID已存在!")
print(f"课程ID校验通过:{course_ID}")
# 课程名称校验
while True:
name=input("请输入课程名称(中英文,长度≥1):")
valid, msg = validate_course_name(name)
if valid:
break
print(f"输入错误:{msg}")
print(f"课程名称校验通过: {name}")
# 授课时间校验
time = []
while True:
time_input = input("请输入课程时间(格式:星期X 时间段,多个时间段用分号分隔,如'周一 8:00-10:00;周三 10:00-12:00'): ")
time_slots = [s.strip() for s in time_input.split(";") if s.strip()]
if not time_slots:
print("输入错误:至少需要一个时间段")
continue
all_valid = True
time = []
for slot in time_slots:
valid, msg = validate_time_slot(slot)
if not valid:
print(f"输入错误:时间段'{slot}' - {msg}")
all_valid = False
break
# 解析时间
day, period = slot.split(" ", 1)
start, end = period.split("-")
time.append((day, start.strip(), end.strip()))
if all_valid:
break
print("授课时间校验通过")
# 课程容量校验
while True:
capacity_str = input("请输入课程容量(正整数,默认50):") or "50"
valid, msg = validate_capacity(capacity_str)
if valid:
capacity = int(capacity_str)
break
print(f"输入错误:{msg}")
print(f"课程容量校验通过:{capacity}")
# 允许专业校验
restrict = input("是否限制专业?(是/否):").strip().lower() == "是"
allowed_majors = []
if restrict:
while True:
majors_str = input("请输入允许修讀此課程的专业(用逗号分隔):")
valid, msg = validate_majors(majors_str)
if valid:
allowed_majors = [m.strip() for m in majors_str.split(",") if m.strip()]
break
print(f"输入错误:{msg}")
print(f"允许专业校验通过: {allowed_majors}")
# 先修课程校验
has_prereq = input("是否有先修课程要求?(是/否): ").strip().lower() == "是"
prerequisites = []
if has_prereq:
existing_courses = list(admin.courses.keys())
if not existing_courses:
print("警告: 系统中暂无其他课程,无法设置先修课程")
else:
while True:
print(f"现有课程: {', '.join(existing_courses)}")
prereqs_str = input("请输入先修课程ID(用逗号分隔):")
valid, msg = validate_prerequisites(prereqs_str, existing_courses)
if valid:
prerequisites = [p.strip() for p in prereqs_str.split(",") if p.strip()]
break
print(f"输入错误:{msg}")
print(f"先修课程校验通过: {prerequisites}")
# 授课地点校验
classroom = input("请输入上课教室:")
if not classroom:
print("警告: 未输入教室信息")
# 创建课程
new_course = Course(course_ID, name, time, capacity, 0, allowed_majors, prerequisites, classroom)
admin.add_course(new_course)
elif choice == "2":
file_path = input("请输入CSV文件路径:")
admin.add_courses_from_csv(file_path)
elif choice == "3":
course_ID= input("请输入要更新的课程ID:")
if course_ID in admin.courses:
print("当前课程信息:")
course = admin.courses[course_ID]
print(f"ID:{course.course_ID},課程名称:{course.name},上課时间:{course.time}")
print(f"容量:{course.capacity}, 当前人数:{course.current_student}")
print(f"允许专业:{course.allowed_majors},先修课程:{course.prerequisites}")
print(f"教室: {course.classroom}")
new_name = input(f"新名称(当前: {course.name}):") or course.name
new_time_input = input(f"新时间(当前: {course.time}):")
if new_time_input:
time_slots = [s.strip() for s in new_time_input.split(";") if s.strip()]
new_time = []
for slot in time_slots:
day, period = slot.split(" ", 1)
start, end = period.split("-")
new_time.append((day, start.strip(), end.strip()))
else:
new_time = course.time
new_capacity_str = input(f"新容量(当前:{course.capacity}):") or str(course.capacity)
valid, msg = validate_capacity(new_capacity_str)
if not valid:
print(f"错误: {msg}")
continue
new_capacity = int(new_capacity_str)
new_classroom = input(f"新教室(当前:{course.classroom}):") or course.classroom
admin.update_course(course_ID, name=new_name, time=new_time, capacity=new_capacity, classroom=new_classroom)
else:
print("课程不存在")
elif choice == "4":
course_ID=input("请输入要删除的课程ID:")
admin.delete_course(course_ID)
elif choice == "5":
print("\n=== 所有课程 ===")
for course_ID, course in admin.courses.items():
print(f"ID: {course_ID}, 名称: {course.name}, 时间: {course.time}")
print(f"容量: {course.capacity}/{course.current_student}, 教室: {course.classroom}")
print(f"允许专业: {course.allowed_majors}, 先修课程:{course.prerequisites}")
print("---")
elif choice == "6":
break
else:
print("无效输入,请重新选择")
# 学生菜单
def student_menu(student, admin):
while True:
print("\n===学生功能頁面===")
print("1.选擇课程")
print("2.退選课程")
print("3.查看课表")
print("4.查看可选课程")
print("5.返回主菜单")
choice = input("请选择功能(1-5):")
if choice =="1":
print("\n===可选课程列表===")
for course_ID,course in admin.courses.items():
if course.current_student < course.capacity:
print(f"ID: {course_ID}, 名称: {course.name}, 时间: {course.time}")
print(f"容量: {course.capacity}/{course.current_student}, 教室: {course.classroom}")
print("---")
course_ID = input("请输入要选的课程ID:")
if course_ID in admin.courses:
student.select_course(admin.courses[course_ID], admin)
else:
print("课程不存在")
elif choice == "2":
if not student.selected_courses:
print("您当前没有选任何课程")
continue
print("\n===已选课程===")
for course in student.selected_courses:
print(f"ID: {course.course_ID}, 名称: {course.name}, 时间: {course.time}")
print("---")
course_ID=input("请输入要退选的课程ID: ")
selected=next((c for c in student.selected_courses if c.course_ID == course_ID), None)
if selected:
student.drop_course(selected)
else:
print("無效退課:您先前未选择该课程")
elif choice == "3":
student.visualize_schedule()
elif choice == "4":
print("\n===所有可选课程===")
for course_ID, course in admin.courses.items():
if course.current_student < course.capacity:
print(f"ID: {course_ID}, 名称: {course.name}, 时间: {course.time}")
print(f"容量: {course.capacity}/{course.current_student}, 教室: {course.classroom}")
print("---")
elif choice=="5":
break
else:
print("无效输入,请重新选择")
# 主程序
if __name__ == "__main__":
# 初始化系统
admin = Admin()
#先添加一些示例课程供演示所用
course1 = Course("CS101", "计算机导论", [("周一", "8:00", "10:00"), ("周三", "10:00", "12:00")],
capacity=30, allowed_majors=["计算机"], prerequisites=["CS100"], classroom="教学楼A301")
course2 = Course("MATH101", "高等数学", [("周二", "1:00", "3:00"), ("周四", "3:00", "5:00")],
capacity=40, classroom="教学楼B202")
course3 = Course("CS102", "数据结构", [("周一", "10:00", "12:00"), ("周三", "8:00", "10:00")],
capacity=25, allowed_majors=["计算机"], prerequisites=["CS101"], classroom="教学楼A302")
course4= Course("FD470", "形势与政策", [("周三", "1:00", "4:00")],
capacity=48, classroom="教学楼A212")
course5= Course("PE102","網球", [("周三", "1:00", "4:00"),("周三","8:00", "10:00")],
capacity=25, classroom="體育館116")
course6= Course("AC352","中级财务会计", [("周三","1:00", "4:00")],
capacity=25, current_student=25, classroom="教学楼C105")
admin.add_course(course1)
admin.add_course(course2)
admin.add_course(course3)
admin.add_course(course4)
admin.add_course(course5)
admin.add_course(course6)
# 主循环
while True:
choice = main_menu()
if choice == "1":
# 管理员登录
print("您的身份:管理员")
admin_menu(admin)
elif choice == "2":
# 学生登录
print("您的身份:学生")
student_id = input("请输入学号:")
major = input("请输入专业:")
student = Student(student_id, major)
student_menu(student, admin)
elif choice == "3":
print("感谢使用,再见!")
break
else:
print("无效选择,请重新输入")