diff --git a/src/file_handler.py b/src/file_handler.py index f044df6..4572a30 100644 --- a/src/file_handler.py +++ b/src/file_handler.py @@ -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 \ No newline at end of file +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" \ No newline at end of file diff --git a/src/main.py b/src/main.py index 38ba1d6..a93d398 100644 --- a/src/main.py +++ b/src/main.py @@ -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__":