165 lines
4.7 KiB
Python
165 lines
4.7 KiB
Python
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
|
|
self._count: int = 0
|
|
|
|
def __str__(self):
|
|
return f"Question<No: {self._no}, Topic: {self._topic}>"
|
|
|
|
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
|
|
|
|
def increase_count(self) -> None:
|
|
self._count += 1
|
|
|
|
def can_pick(self, max_count: int) -> bool:
|
|
return self._count <= max_count
|
|
|
|
|
|
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<No: {self._no}, SO: {self._so}, Name: {self._name}, Major: {self._major}, Class: {self._class_name}>"
|
|
|
|
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, max_count: int = 3) -> None:
|
|
available_questions = [q for q in questions if q.can_pick(max_count)]
|
|
|
|
if len(available_questions) < num:
|
|
raise ValueError("Not enough questions with count <= max_count")
|
|
self._picked_questions = random.sample(available_questions, num)
|
|
|
|
for q in self._picked_questions:
|
|
q.increase_count()
|
|
|
|
class Course:
|
|
def __init__(self, name: str):
|
|
self._name = name
|
|
|
|
def __str__(self):
|
|
return f"Course<Name: {self._name}>"
|
|
|
|
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__':
|
|
...
|