|
@@ -163,6 +163,7 @@ class ExamQuestionOption(models.Model):
|
|
|
|
|
|
@classmethod
|
|
|
def validate(cls, type, options, answer):
|
|
|
+ # 检查选项有效性
|
|
|
if not options:
|
|
|
raise CustomError(f'选项不能为空')
|
|
|
if len(options) < 2:
|
|
@@ -170,32 +171,33 @@ class ExamQuestionOption(models.Model):
|
|
|
if len(options) > 10:
|
|
|
raise CustomError(f'选项不能多于10个')
|
|
|
|
|
|
- answers = list(answer)
|
|
|
+ # 处理答案
|
|
|
+ answers = list(answer) # 转换答案为列表,支持多个字符
|
|
|
answers_len = len(answers)
|
|
|
+
|
|
|
+ # 单选题只能选择一个答案
|
|
|
if type == ExamQuestion.SINGLE and answers_len > 1:
|
|
|
raise CustomError(f'单选题答案只能有一个')
|
|
|
-
|
|
|
+
|
|
|
+ # 验证答案中的字母是否合法
|
|
|
alphabet = string.ascii_uppercase # 包含 A 到 Z 的字母序列
|
|
|
- cycle_alphabet = itertools.cycle(alphabet) # 创建无限循环的字母序列
|
|
|
- all_chars = list(itertools.islice(cycle_alphabet, answers_len)) # 截取所需长度的部分
|
|
|
+ valid_answers = set(alphabet[:len(options)]) # 只考虑合法的字母选项
|
|
|
|
|
|
- if len(set(answers).difference(all_chars)) > 0:
|
|
|
- raise CustomError(f'答案选项无效,可选项有:{all_chars}')
|
|
|
-
|
|
|
+ if not all(answer in valid_answers for answer in answers):
|
|
|
+ raise CustomError(f'答案选项无效,可选项有:{", ".join(valid_answers)}')
|
|
|
+
|
|
|
+ # 生成验证数据
|
|
|
validation_data = []
|
|
|
- index = 0
|
|
|
- for option in options:
|
|
|
+ for index, option in enumerate(options):
|
|
|
item = {
|
|
|
'content': option,
|
|
|
'right': False
|
|
|
}
|
|
|
- for letter in answers:
|
|
|
- if index == ord(letter) - ord('A'):
|
|
|
- item['right'] = True
|
|
|
- break
|
|
|
- index += 1
|
|
|
+ if chr(ord('A') + index) in answers: # 使用字母索引进行匹配
|
|
|
+ item['right'] = True
|
|
|
|
|
|
validation_data.append(item)
|
|
|
+
|
|
|
return validation_data
|
|
|
|
|
|
|