|
|
|
|
@ -1,107 +1,105 @@
|
|
|
|
|
import random
|
|
|
|
|
from user_manager import AccountType
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MathQuestion:
|
|
|
|
|
"""题目类,包含题目内容和对应的难度类型"""
|
|
|
|
|
def __init__(self, content: str, question_type: AccountType):
|
|
|
|
|
self.content = content
|
|
|
|
|
self.type = question_type
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other) -> bool:
|
|
|
|
|
"""重载==运算符,用于题目查重"""
|
|
|
|
|
if not isinstance(other, MathQuestion):
|
|
|
|
|
return False
|
|
|
|
|
return self.content == other.content and self.type == other.type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class QuestionGenerator:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
random.seed() # 初始化随机种子
|
|
|
|
|
|
|
|
|
|
def generate_questions(self, count: int, question_type: AccountType) -> list[MathQuestion]:
|
|
|
|
|
"""
|
|
|
|
|
生成指定数量和难度的题目列表
|
|
|
|
|
:param count: 题目数量
|
|
|
|
|
:param question_type: 题目难度类型
|
|
|
|
|
:return: 题目对象列表
|
|
|
|
|
"""
|
|
|
|
|
questions = []
|
|
|
|
|
while len(questions) < count:
|
|
|
|
|
if question_type == AccountType.PRIMARY_SCHOOL:
|
|
|
|
|
content = self._generate_primary_question()
|
|
|
|
|
elif question_type == AccountType.MIDDLE_SCHOOL:
|
|
|
|
|
content = self._generate_middle_question()
|
|
|
|
|
elif question_type == AccountType.HIGH_SCHOOL:
|
|
|
|
|
content = self._generate_high_question()
|
|
|
|
|
else:
|
|
|
|
|
continue # 无效类型跳过
|
|
|
|
|
# 去重(避免生成完全相同的题目)
|
|
|
|
|
new_question = MathQuestion(content, question_type)
|
|
|
|
|
if new_question not in questions:
|
|
|
|
|
questions.append(new_question)
|
|
|
|
|
return questions
|
|
|
|
|
|
|
|
|
|
def _generate_random_num(self) -> int:
|
|
|
|
|
"""生成1-100之间的随机整数"""
|
|
|
|
|
return random.randint(1, 100)
|
|
|
|
|
|
|
|
|
|
def _generate_expression(self, op_count: int, ops: list[str]) -> str:
|
|
|
|
|
"""
|
|
|
|
|
生成包含指定数量操作数和运算符的表达式
|
|
|
|
|
:param op_count: 操作数数量(1-5)
|
|
|
|
|
:param ops: 可用运算符列表
|
|
|
|
|
:return: 表达式字符串
|
|
|
|
|
"""
|
|
|
|
|
if op_count < 1:
|
|
|
|
|
return ""
|
|
|
|
|
# 初始化第一个操作数
|
|
|
|
|
expr_parts = [str(self._generate_random_num())]
|
|
|
|
|
for _ in range(op_count - 1):
|
|
|
|
|
op = random.choice(ops)
|
|
|
|
|
# 除法确保除数不为0且能整除,避免小数
|
|
|
|
|
if op == "/":
|
|
|
|
|
divisor = self._generate_random_num()
|
|
|
|
|
dividend = self._generate_random_num() * divisor
|
|
|
|
|
expr_parts.append(op)
|
|
|
|
|
expr_parts.append(str(divisor))
|
|
|
|
|
else:
|
|
|
|
|
expr_parts.append(op)
|
|
|
|
|
expr_parts.append(str(self._generate_random_num()))
|
|
|
|
|
return " ".join(expr_parts)
|
|
|
|
|
|
|
|
|
|
def _add_parentheses(self, expr: str) -> str:
|
|
|
|
|
"""30%概率为表达式添加括号"""
|
|
|
|
|
if random.random() < 0.3 and len(expr.split()) >= 3: # 至少包含一个运算符才加括号
|
|
|
|
|
return f"({expr})"
|
|
|
|
|
return expr
|
|
|
|
|
|
|
|
|
|
def _generate_primary_question(self) -> str:
|
|
|
|
|
"""生成小学题目(仅+、-、*、/和())"""
|
|
|
|
|
op_count = random.randint(1, 5) # 1-5个操作数
|
|
|
|
|
ops = ["+", "-", "*", "/"]
|
|
|
|
|
expr = self._generate_expression(op_count, ops)
|
|
|
|
|
return self._add_parentheses(expr)
|
|
|
|
|
|
|
|
|
|
def _generate_middle_question(self) -> str:
|
|
|
|
|
"""生成初中题目(包含平方或开根号,可含+、-、*、/和())"""
|
|
|
|
|
op_count = random.randint(1, 5)
|
|
|
|
|
ops = ["+", "-", "*", "/"]
|
|
|
|
|
expr = self._generate_expression(op_count, ops)
|
|
|
|
|
# 确保包含平方或开根号
|
|
|
|
|
func_choice = random.choice(["square", "sqrt"])
|
|
|
|
|
if func_choice == "square":
|
|
|
|
|
expr = self._add_parentheses(expr) + " ^ 2"
|
|
|
|
|
else:
|
|
|
|
|
expr = f"sqrt({self._add_parentheses(expr)})"
|
|
|
|
|
return expr
|
|
|
|
|
|
|
|
|
|
def _generate_high_question(self) -> str:
|
|
|
|
|
"""生成高中题目(包含sin、cos、tan,可含+、-、*、/和())"""
|
|
|
|
|
op_count = random.randint(1, 5)
|
|
|
|
|
ops = ["+", "-", "*", "/"]
|
|
|
|
|
expr = self._generate_expression(op_count, ops)
|
|
|
|
|
# 确保包含三角函数
|
|
|
|
|
trig_func = random.choice(["sin", "cos", "tan"])
|
|
|
|
|
expr = f"{trig_func}({self._add_parentheses(expr)})"
|
|
|
|
|
return expr
|
|
|
|
|
import random
|
|
|
|
|
from user_manager import AccountType
|
|
|
|
|
from typing import List
|
|
|
|
|
|
|
|
|
|
class MathQuestion:
|
|
|
|
|
"""题目类,包含题目内容和对应的难度类型"""
|
|
|
|
|
def __init__(self, content: str, question_type: AccountType):
|
|
|
|
|
self.content = content
|
|
|
|
|
self.type = question_type
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other) -> bool:
|
|
|
|
|
"""重载==运算符,用于题目查重"""
|
|
|
|
|
if not isinstance(other, MathQuestion):
|
|
|
|
|
return False
|
|
|
|
|
return self.content == other.content and self.type == other.type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class QuestionGenerator:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
random.seed() # 初始化随机种子
|
|
|
|
|
|
|
|
|
|
def generate_questions(self, count: int, question_type: AccountType) -> List[MathQuestion]:
|
|
|
|
|
"""生成指定数量和难度的题目列表(去重)"""
|
|
|
|
|
questions = []
|
|
|
|
|
seen = set()
|
|
|
|
|
while len(questions) < count:
|
|
|
|
|
content = self.generate_question(question_type)
|
|
|
|
|
new_question = MathQuestion(content, question_type)
|
|
|
|
|
if new_question not in questions:
|
|
|
|
|
questions.append(new_question)
|
|
|
|
|
return questions
|
|
|
|
|
|
|
|
|
|
def _generate_random_num(self) -> int:
|
|
|
|
|
"""生成1-100之间的随机整数"""
|
|
|
|
|
return random.randint(1, 100)
|
|
|
|
|
|
|
|
|
|
def _generate_expression(self, op_count: int, ops: list[str]) -> str:
|
|
|
|
|
"""
|
|
|
|
|
生成包含指定数量操作数和运算符的表达式
|
|
|
|
|
:param op_count: 操作数数量(1-5)
|
|
|
|
|
:param ops: 可用运算符列表
|
|
|
|
|
:return: 表达式字符串
|
|
|
|
|
"""
|
|
|
|
|
if op_count < 1:
|
|
|
|
|
return ""
|
|
|
|
|
# 初始化第一个操作数
|
|
|
|
|
expr_parts = [str(self._generate_random_num())]
|
|
|
|
|
for _ in range(op_count - 1):
|
|
|
|
|
op = random.choice(ops)
|
|
|
|
|
# 除法确保除数不为0且能整除,避免小数
|
|
|
|
|
if op == "/":
|
|
|
|
|
divisor = self._generate_random_num()
|
|
|
|
|
dividend = self._generate_random_num() * divisor
|
|
|
|
|
expr_parts.append(op)
|
|
|
|
|
expr_parts.append(str(divisor))
|
|
|
|
|
else:
|
|
|
|
|
expr_parts.append(op)
|
|
|
|
|
expr_parts.append(str(self._generate_random_num()))
|
|
|
|
|
return " ".join(expr_parts)
|
|
|
|
|
|
|
|
|
|
def _add_parentheses(self, expr: str) -> str:
|
|
|
|
|
"""30%概率为表达式添加括号"""
|
|
|
|
|
if random.random() < 0.3 and len(expr.split()) >= 3: # 至少包含一个运算符才加括号
|
|
|
|
|
return f"({expr})"
|
|
|
|
|
return expr
|
|
|
|
|
|
|
|
|
|
def _generate_primary_question(self) -> str:
|
|
|
|
|
"""生成小学题目(仅+、-、*、/和())"""
|
|
|
|
|
op_count = random.randint(1, 5) # 1-5个操作数
|
|
|
|
|
ops = ["+", "-", "*", "/"]
|
|
|
|
|
expr = self._generate_expression(op_count, ops)
|
|
|
|
|
return self._add_parentheses(expr)
|
|
|
|
|
|
|
|
|
|
def _generate_middle_question(self) -> str:
|
|
|
|
|
"""生成初中题目(包含平方或开根号,可含+、-、*、/和())"""
|
|
|
|
|
op_count = random.randint(1, 5)
|
|
|
|
|
ops = ["+", "-", "*", "/"]
|
|
|
|
|
expr = self._generate_expression(op_count, ops)
|
|
|
|
|
# 确保包含平方或开根号
|
|
|
|
|
func_choice = random.choice(["square", "sqrt"])
|
|
|
|
|
if func_choice == "square":
|
|
|
|
|
expr = self._add_parentheses(expr) + " ^ 2"
|
|
|
|
|
else:
|
|
|
|
|
expr = f"sqrt({self._add_parentheses(expr)})"
|
|
|
|
|
return expr
|
|
|
|
|
|
|
|
|
|
def _generate_high_question(self) -> str:
|
|
|
|
|
"""生成高中题目(包含sin、cos、tan,可含+、-、*、/和())"""
|
|
|
|
|
op_count = random.randint(1, 5)
|
|
|
|
|
ops = ["+", "-", "*", "/"]
|
|
|
|
|
expr = self._generate_expression(op_count, ops)
|
|
|
|
|
# 确保包含三角函数
|
|
|
|
|
trig_func = random.choice(["sin", "cos", "tan"])
|
|
|
|
|
expr = f"{trig_func}({self._add_parentheses(expr)})"
|
|
|
|
|
return expr
|
|
|
|
|
# 新增公共接口方法,根据难度生成题目
|
|
|
|
|
def generate_question(self, account_type: AccountType) -> str:
|
|
|
|
|
if account_type == AccountType.PRIMARY_SCHOOL:
|
|
|
|
|
return self._generate_primary_question()
|
|
|
|
|
elif account_type == AccountType.MIDDLE_SCHOOL:
|
|
|
|
|
return self._generate_middle_question()
|
|
|
|
|
elif account_type == AccountType.HIGH_SCHOOL:
|
|
|
|
|
return self._generate_high_question()
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError("无效的账户类型")
|