import random from typing import Optional, Tuple, NoReturn from openpyxl.reader.excel import load_workbook class Question: def __init__(self, no: str, topic: str): self._no: str = no self._topic: str = topic def __str__(self): return f"Question" def __repr__(self): return self.__str__() @staticmethod def load_from_csv(path: Optional[str] = None) -> list['Question']: questions = [] with open(path if path else '../files/questions.csv', encoding='gbk') as f: for line in f.readlines(): questions.append(Question(*line.strip('\n').split(','))) return questions @staticmethod def load_from_xls(path: str) -> list['Question']: questions = [] wb = load_workbook(path, read_only=True) ws = wb.active for row in ws.iter_rows(min_col=2, max_col=3, min_row=2, values_only=True): if row[0] is None and row[1] is None: break questions.append(Question(*row)) wb.close() return questions @property def no(self) -> str: return self._no @property def topic(self) -> str: return self._topic class Student: def __init__(self, no: str, so: str, name: str, major: str, class_name: str): self._no: str = no self._so: str = so self._name: str = name self._major: str = major self._class_name: str = class_name self._picked_questions: list[Question] = [] def __str__(self): return f"Student" def __repr__(self): return self.__str__() @staticmethod def load_from_xls(path: str) -> list['Student'] | NoReturn: wb = load_workbook(path, read_only=True) ws = wb.active students = [] if ws.title == 'Sheet1': for row in ws.iter_rows(min_row=6, max_col=5, values_only=True): students.append(Student(*row)) elif ws.title == '初始录入': for row in ws.iter_rows(min_row=13, max_col=5, values_only=True): students.append(Student(*row)) else: raise Exception("无法解析学生名单") wb.close() return [x for x in students if x.valid] @property def valid(self) -> bool: return bool(self._no and self._so and self._name and self._major and self._class_name) @property def picked_questions(self) -> list[Question]: return self._picked_questions @property def no(self) -> str: return self._no @property def so(self) -> str: return self._so @property def name(self) -> str: return self._name @property def major(self) -> str: return self._major @property def class_name(self) -> str: return self._class_name def pick_question(self, questions: list[Question], num: int = 3) -> None: if len(questions) < num: raise ValueError("Not enough questions to pick from.") self._picked_questions = random.sample(questions, num) class Course: def __init__(self, name: str): self._name = name def __str__(self): return f"Course" def __repr__(self): return self.__str__() @staticmethod def load_from_xls(path: str) -> 'Course' | NoReturn: wb = load_workbook(path, read_only=True) ws = wb.active if ws.title == 'Sheet1': name: str = ws['E3'].value[5:] elif ws.title == '初始录入': name: str = ws['D5'].value else: raise Exception("无法解析课程名") wb.close() return Course(name) @property def name(self) -> str: return self._name class Performance: def __init__(self, scores: Tuple[float, float, float], rates: Tuple[float, float, float], achievement: float): self.scores = scores # (平时平均分, 大作业平均分, 试卷平均分) self.rates = rates # (平时得分率, 大作业得分率, 试卷得分率) self.achievement = achievement # 达成度 def __str__(self): return f"Performance(scores={self.scores}, rates={self.rates}, achievement={self.achievement})" if __name__ == '__main__': ...