1 #4

Merged
hnu202326010322 merged 2 commits from develop into main 5 months ago

@ -1,102 +1,112 @@
import os
import datetime
from user_manager import AccountType
from question_generator import MathQuestion
class FileHandler:
def __init__(self, username: str):
"""
初始化文件处理器
:param username: 用户名用于创建专属文件夹
"""
self.username = username
self.user_dir = f"{username}_questions/" # 用户专属文件夹
self._create_user_dir()
def _create_user_dir(self) -> None:
"""创建用户专属文件夹(若不存在)"""
if not os.path.exists(self.user_dir):
os.makedirs(self.user_dir)
@staticmethod
def _get_current_time_str() -> str:
"""获取当前时间字符串,格式:年-月-日-时-分-秒"""
return datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
def _read_existing_questions(self) -> list[MathQuestion]:
"""读取用户文件夹下所有历史题目,用于查重"""
existing_questions = []
if not os.path.exists(self.user_dir):
return existing_questions
# 遍历文件夹下所有txt文件
for filename in os.listdir(self.user_dir):
if not filename.endswith(".txt"):
continue
file_path = os.path.join(self.user_dir, filename)
# 从文件名提取题目类型
if "小学" in filename:
question_type = AccountType.PRIMARY_SCHOOL
elif "初中" in filename:
question_type = AccountType.MIDDLE_SCHOOL
elif "高中" in filename:
question_type = AccountType.HIGH_SCHOOL
else:
continue
# 读取文件内容
try:
with open(file_path, "r", encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if not line or not line[0].isdigit():
continue
# 提取题目内容(去掉题号,如"1. 2 + 3" → "2 + 3"
content_start = line.find(". ") + 2
if content_start > 1:
content = line[content_start:]
existing_questions.append(MathQuestion(content, question_type))
except IOError as e:
print(f"读取文件 {file_path} 时发生错误: {e}")
return existing_questions
def is_duplicate(self, question: MathQuestion) -> bool:
"""
检查题目是否已存在于历史文件中
:param question: 待检查的题目对象
:return: 存在返回True否则返回False
"""
existing = self._read_existing_questions()
return question in existing
def save_questions(self, questions: list[MathQuestion]) -> bool:
"""
将题目保存到文件
:param questions: 待保存的题目列表
:return: 保存成功返回True失败返回False
"""
if not questions:
return False
# 确定题目类型(所有题目类型一致)
question_type = questions[0].type
if question_type == AccountType.PRIMARY_SCHOOL:
type_str = "小学"
elif question_type == AccountType.MIDDLE_SCHOOL:
type_str = "初中"
elif question_type == AccountType.HIGH_SCHOOL:
type_str = "高中"
else:
return False
# 生成文件名
time_str = self._get_current_time_str()
filename = f"{time_str}_{type_str}.txt"
file_path = os.path.join(self.user_dir, filename)
# 写入文件
try:
with open(file_path, "w", encoding="utf-8") as f:
for idx, question in enumerate(questions, 1):
f.write(f"{idx}. {question.content}\n\n") # 每题带题号,空行分隔
return True
except IOError as e:
print(f"保存文件 {file_path} 时发生错误: {e}")
return False
import os
import datetime
from user_manager import AccountType
from question_generator import MathQuestion
class FileHandler:
def __init__(self, username: str):
"""
初始化文件处理器
:param username: 用户名用于创建专属文件夹
"""
self.username = username
self.user_dir = f"{username}_questions/" # 用户专属文件夹
self._create_user_dir()
def _create_user_dir(self) -> None:
"""创建用户专属文件夹(若不存在)"""
if not os.path.exists(self.user_dir):
os.makedirs(self.user_dir)
@staticmethod
def _get_current_time_str() -> str:
"""获取当前时间字符串,格式:年-月-日-时-分-秒"""
return datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
def _read_existing_questions(self) -> list[MathQuestion]:
"""读取用户文件夹下所有历史题目,用于查重"""
existing_questions = []
if not os.path.exists(self.user_dir):
return existing_questions
# 遍历文件夹下所有txt文件
for filename in os.listdir(self.user_dir):
if not filename.endswith(".txt"):
continue
file_path = os.path.join(self.user_dir, filename)
# 从文件名提取题目类型
if "小学" in filename:
question_type = AccountType.PRIMARY_SCHOOL
elif "初中" in filename:
question_type = AccountType.MIDDLE_SCHOOL
elif "高中" in filename:
question_type = AccountType.HIGH_SCHOOL
else:
continue
# 读取文件内容
try:
with open(file_path, "r", encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if not line or not line[0].isdigit():
continue
# 提取题目内容(去掉题号,如"1. 2 + 3" → "2 + 3"
content_start = line.find(". ") + 2
if content_start > 1:
content = line[content_start:]
existing_questions.append(MathQuestion(content, question_type))
except IOError as e:
print(f"读取文件 {file_path} 时发生错误: {e}")
return existing_questions
def is_duplicate(self, question: MathQuestion) -> bool:
"""
检查题目是否已存在于历史文件中
:param question: 待检查的题目对象
:return: 存在返回True否则返回False
"""
existing = self._read_existing_questions()
return question in existing
def save_questions(self, questions: list[MathQuestion]) -> bool:
"""
将题目保存到文件
:param questions: 待保存的题目列表
:return: 保存成功返回True失败返回False
"""
if not questions:
return False
# 确定题目类型(所有题目类型一致)
question_type = questions[0].type
if question_type == AccountType.PRIMARY_SCHOOL:
type_str = "小学"
elif question_type == AccountType.MIDDLE_SCHOOL:
type_str = "初中"
elif question_type == AccountType.HIGH_SCHOOL:
type_str = "高中"
else:
return False
# 生成文件名
time_str = self._get_current_time_str()
filename = f"{time_str}_{type_str}.txt"
file_path = os.path.join(self.user_dir, filename)
# 写入文件
try:
with open(file_path, "w", encoding="utf-8") as f:
for idx, question in enumerate(questions, 1):
f.write(f"{idx}. {question.content}\n\n") # 每题带题号,空行分隔
return True
except IOError as e:
print(f"保存文件 {file_path} 时发生错误: {e}")
return False
# file_handler.py 中新增方法
def get_filename_by_type(self, type_str: str) -> str:
"""
根据题目类型生成标准文件名 save_questions 逻辑一致
:param type_str: 题目类型字符串"小学"
:return: 生成的文件名
"""
time_str = self._get_current_time_str()
return f"{time_str}_{type_str}.txt"

@ -17,62 +17,76 @@ def split_username_password(input_str: str) -> tuple[str, str]:
def log_in_process(user_manager: UserManager) -> tuple[str, AccountType]:
"""登录流程,循环直到输入正确的用户名密码"""
while True:
input_str = input("请输入用户名和密码(空格隔):")
input_str = input("请输入用户名和密码(空格隔")
username, password = split_username_password(input_str)
account_type = user_manager.verify_user(username, password)
if account_type != AccountType.INVALID:
print(f"登录成功!欢迎{username}")
print(f"当前选择为{user_manager.type_to_str(account_type)}出题")
return username, account_type
else:
print("请输入正确的用户名、密码")
print("请输入正确的用户名、密码")
def handle_question_generation(question_generator, current_type, file_handler, user_manager):
"""处理题目生成逻辑新增user_manager参数"""
while True:
count_str = input(
f"准备生成{user_manager.type_to_str(current_type)}数学题目,请输入数量(10-30-1退出): "
).strip()
if count_str == "-1":
print("退出当前用户")
return True
if count_str.isdigit():
question_count = int(count_str)
if 10 <= question_count <= 30:
generated_questions = []
while len(generated_questions) < question_count:
content = question_generator.generate_question(current_type)
new_question = MathQuestion(content, current_type)
if not file_handler.is_duplicate(new_question):
generated_questions.append(new_question)
if file_handler.save_questions(generated_questions):
print(f"题目生成成功!共{question_count}题,已保存至{file_handler.user_dir}")
else:
print("题目保存失败,请重试")
return False
print("题目数量无效请输入10-30之间的整数")
else:
print("请输入有效的整数")
def parse_input(input_str: str, current_type: AccountType, user_manager: UserManager) -> tuple[int, AccountType | None]:
"""解析输入:返回题目数量(-1退出0无效和新难度类型None不变"""
input_str = input_str.strip()
# 处理难度切换指令
if input_str == "切换为小学":
return 0, AccountType.PRIMARY_SCHOOL
elif input_str == "切换为初中":
return 0, AccountType.MIDDLE_SCHOOL
elif input_str == "切换为高中":
return 0, AccountType.HIGH_SCHOOL
# 处理退出指令
elif input_str == "-1":
return -1, None
# 处理题目数量输入
elif input_str.isdigit():
count = int(input_str)
return count if 10 <= count <= 30 else 0, None
# 无效输入
return 0, None
def handle_difficulty_switch(user_manager):
"""处理难度切换逻辑"""
def handle_question_flow(question_generator, current_type, file_handler, user_manager):
"""处理题目生成与难度切换的循环流程"""
while True:
print("1. 小学(+,-,*,/,括号)")
print("2. 初中(包含平方、开根号)")
print("3. 高中(包含三角函数)")
print("0. 返回主菜单")
level_choice = input("请选择难度级别: ").strip()
if level_choice.isdigit():
level = int(level_choice)
if level == 0:
return None
new_type = user_manager.parse_type_choice(level)
if new_type != AccountType.INVALID:
print(f"已成功切换为{user_manager.type_to_str(new_type)}难度")
return new_type
print("请输入有效的选项")
type_str = user_manager.type_to_str(current_type)
input_str = input(
f"准备生成{type_str}数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录"
)
question_count, new_type = parse_input(input_str, current_type, user_manager)
if new_type:
# 切换难度
current_type = new_type
print(f"当前选择为{user_manager.type_to_str(current_type)}出题")
elif question_count == -1:
# 退出当前用户
print("已退出当前用户")
return
elif 10 <= question_count <= 30:
# 生成题目
print(f"正在生成{question_count}{type_str}数学题目...")
generated = []
while len(generated) < question_count:
content = question_generator.generate_question(current_type)
q = MathQuestion(content, current_type)
if not file_handler.is_duplicate(q):
generated.append(q)
# 保存并预览
if file_handler.save_questions(generated):
# main.py 中生成文件名的地方
filename = file_handler.get_filename_by_type(type_str)
print(f"题目已保存到文件:{type_str}/{filename}")
print(f"共生成{question_count}道题目\n")
# 预览前3道题
print("题目预览:")
for i, q in enumerate(generated[:3], 1):
print(f"{i}. {q.content}")
if len(generated) > 3:
print("...\n")
else:
print("输入无效,请重新输入\n")
def main():
@ -82,31 +96,7 @@ def main():
while True:
username, current_type = log_in_process(user_manager)
file_handler = FileHandler(username)
while True:
print(f"\n当前用户: {username}|当前难度: {user_manager.type_to_str(current_type)}")
print("1. 生成题目")
print("2. 切换难度级别")
print("3. 退出当前用户")
print("4. 退出程序")
choice = input("请选择操作(1-4): ").strip()
if choice == "1":
# 调用时传入user_manager参数
if handle_question_generation(question_generator, current_type, file_handler, user_manager):
break
elif choice == "2":
new_type = handle_difficulty_switch(user_manager)
if new_type:
current_type = new_type
elif choice == "3":
print("退出当前用户")
break
elif choice == "4":
print("退出程序")
return
else:
print("请输入有效的选项(1-4)")
handle_question_flow(question_generator, current_type, file_handler, user_manager)
if __name__ == "__main__":

Loading…
Cancel
Save