main_develop #1

Merged
hnu202326010330 merged 7 commits from develop into main 5 months ago

@ -0,0 +1,9 @@
from abc import ABC, abstractmethod
class BaseQuestionGenerator(ABC):
"""抽象类:定义题目生成器接口"""
@abstractmethod
def generate_question(self):
"""生成一条题目"""
pass

@ -0,0 +1,161 @@
import os
from history_manager import HistoryManager
from junior_generator import JuniorQuestionGenerator
from primary_generator import PrimaryQuestionGenerator
from senior_generator import SeniorQuestionGenerator
#查重功能在_generate_and_save_questions函数中实现
class ExamGenerator:
def __init__(self):
self.accounts = {
"小学": [("张三1", "123"), ("张三2", "123"), ("张三3", "123")],
"初中": [("李四1", "123"), ("李四2", "123"), ("李四3", "123")],
"高中": [("王五1", "123"), ("王五2", "123"), ("王五3", "123")]
}
self.level = None
self.username = None
self.folder = None
self.history = set()
self.history_manager = HistoryManager()
def get_account_type(self, username, password):
"""根据用户名和密码获取用户等级(角色)"""
for level, infos in self.accounts.items():
if (username, password) in infos:
return level
return None
def get_generator(self, level):
"""根据等级获取对应的题目生成器"""
if level == "小学":
return PrimaryQuestionGenerator()
elif level == "初中":
return JuniorQuestionGenerator()
elif level == "高中":
return SeniorQuestionGenerator()
return None
def run(self):
"""
程序主入口控制整体流程
"""
print("--- 欢迎使用数学题库生成系统 ---")
while True:
# 1. 处理登录
if not self._login():
print("感谢使用,再见!")
break # 退出整个程序
# 2. 登录成功后,进入主菜单循环
self._main_menu()
# 3. 从主菜单退出后,重置用户状态,准备下一次登录
self._reset_user_state()
def _login(self):
"""
处理用户登录流程
返回: 如果登录成功返回 True如果用户选择退出返回 False
"""
while True:
login_input = input("请输入用户名和密码(以空格分隔),或输入 -1 退出:").strip()
if login_input == "-1":
return False
if " " not in login_input:
print("输入格式错误,请输入用户名和密码,以空格分隔。")
continue
username, password = login_input.split(" ", 1)
level = self.get_account_type(username, password)
if level:
self.username = username
self.level = level
self.folder = os.path.join("exams", self.username)
self.history = self.history_manager.load_history(self.folder)
print(f"\n登录成功!当前用户:{self.username},当前等级:{self.level}")
return True
else:
print("用户名或密码错误,请重新输入。")
def _main_menu(self):
"""
登录后的主菜单和命令处理循环
"""
while True:
# 根据当前等级获取生成器
generator = self.get_generator(self.level)
if not generator:
print("无法获取题目生成器,请联系管理员。")
break
cmd = input(f"\n请输入操作:\n"
f"1. 直接输入数量 10-30(生成 {self.level} 数学题目)\n"
f"2. 直接输入 '切换为小学/初中/高中'(切换等级)\n"
f"3. 直接输入 -1(返回登录界面)\n"
f"请输入您的选择:").strip()
if cmd == "-1":
print("\n正在退出当前用户...")
break # 退出主菜单循环
# 解析并执行命令
self._process_command(cmd, generator)
def _process_command(self, cmd, generator):
"""
解析并执行用户在主菜单中输入的命令
"""
if cmd.startswith("切换为"):
new_level = cmd[3:].strip()
if new_level in ["小学", "初中", "高中"]:
self.level = new_level
print(f"系统提示:已成功切换为 {self.level} 等级。")
else:
print("切换失败,请输入 '切换为小学''切换为初中''切换为高中'")
elif cmd.isdigit():
num = int(cmd)
if 10 <= num <= 30:
self._generate_and_save_questions(num, generator)
else:
print("无效数量,请输入 10 到 30 之间的数字。")
else:
print("无效的命令,请重新输入。")
#查重功能
def _generate_and_save_questions(self, num, generator):
"""
生成指定数量的不重复题目并保存到文件和历史记录中
"""
print(f"正在为您生成 {num}{self.level} 数学题目...")
questions = []
while len(questions) < num:
q = generator.generate_question()
# 确保题目既不在历史记录中,也不在本次生成的临时列表中
if q not in self.history and q not in questions:
questions.append(q)
# 保存题目
self.history_manager.save_questions(self.folder, questions)
# 更新内存中的历史记录
self.history.update(questions)
print(f"✅ 成功生成并保存 {num}{self.level} 数学题目!")
def _reset_user_state(self):
"""
重置所有与当前用户相关的状态以便下一个用户登录
"""
self.username = None
self.level = None
self.folder = None
self.history = set()

@ -0,0 +1,22 @@
import os
from datetime import datetime
class HistoryManager:
def load_history(self, folder):
history = set()
if not os.path.exists(folder):
os.makedirs(folder)
return history
for file in os.listdir(folder):
if file.endswith(".txt"):
with open(os.path.join(folder, file), "r", encoding="utf-8") as f:
history.update(line.strip() for line in f if line.strip())
return history
def save_questions(self, folder, questions):
filename = datetime.now().strftime("%Y-%m-%d-%H-%M-%S.txt")
filepath = os.path.join(folder, filename)
with open(filepath, "w", encoding="utf-8") as f:
for i, q in enumerate(questions, 1):
f.write(f"{i}. {q}\n\n")
print(f"题目已保存到 {filepath}")

@ -0,0 +1,26 @@
import random
from base_generator import BaseQuestionGenerator
class JuniorQuestionGenerator(BaseQuestionGenerator):
def generate_question(self):
ops = ["+", "-", "*", "/"]
num_operands = random.randint(2, 5)
nums = [str(random.randint(1, 50)) for _ in range(num_operands)]
# 1. 初始化一个列表,将第一个数字作为初始元素
parts = [nums[0]]
# 2. 在循环中,将操作符和数字组成的子字符串追加到列表
for n in nums[1:]:
parts.append(" " + random.choice(ops) + " " + n)
# 3. 使用 "".join() 将列表中的所有部分一次性拼接成字符串
expr = "".join(parts)
# 后续逻辑保持不变
if random.choice([True, False]):
expr = f"({expr})^2"
else:
expr = f"√({expr})"
return expr

@ -0,0 +1,5 @@
from exam_generator import ExamGenerator
if __name__ == "__main__":
generator = ExamGenerator()
generator.run()

@ -0,0 +1,23 @@
import random
from base_generator import BaseQuestionGenerator
class PrimaryQuestionGenerator(BaseQuestionGenerator):
def generate_question(self):
ops = ["+", "-", "*"]
while True:
num_operands = random.randint(2, 4) # 控制操作数数量
nums = [random.randint(1, 20) for _ in range(num_operands)]
chosen_ops = [random.choice(ops) for _ in range(num_operands - 1)]
# 构造表达式字符串
expr = str(nums[0])
for i in range(1, num_operands):
expr += f" {chosen_ops[i-1]} {nums[i]}"
try:
result = eval(expr)
except ZeroDivisionError:
continue # 避免除零错误
if result > 0 and isinstance(result, int):
return expr

@ -0,0 +1,15 @@
import random
from base_generator import BaseQuestionGenerator
class SeniorQuestionGenerator(BaseQuestionGenerator):
def generate_question(self):
ops = ["+", "-", "*", "/"]
num_operands = random.randint(2, 5)
nums = [str(random.randint(1, 100)) for _ in range(num_operands)]
func = random.choice(["sin", "cos", "tan"])
expr = nums[0]
for n in nums[1:]:
expr += " " + random.choice(ops) + " " + n
return f"{func}({expr})"
Loading…
Cancel
Save