diff --git a/.vscode/settings.json b/.vscode/settings.json index a8b20bb..f67432d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -77,7 +77,8 @@ "ranges": "cpp", "span": "cpp", "stack": "cpp", - "text_encoding": "cpp" + "text_encoding": "cpp", + "codecvt": "cpp" }, "C_Cpp_Runner.cCompilerPath": "gcc", "C_Cpp_Runner.cppCompilerPath": "g++", diff --git a/frontend/shared/backend_interface.h b/frontend/shared/backend_interface.h index 3782690..05d6f11 100644 --- a/frontend/shared/backend_interface.h +++ b/frontend/shared/backend_interface.h @@ -1,117 +1,122 @@ -#ifndef DATA_STRUCTURES_H -#define DATA_STRUCTURES_H +#ifndef BACKEND_INTERFACE_H +#define BACKEND_INTERFACE_H #include #include +#include +#include +#include +#include "../../src/exam_system/exam_system.h" -// 用户信息结构体 -struct UserInfo { - std::string email; - std::string password; - bool isLoggedIn = false; -}; +namespace exam_system { // 题目信息结构体 struct QuestionInfo { int id; std::string content; std::vector options; - int correctAnswer; // 0-3 对应ABCD + int correct_answer; // 0-3 对应ABCD }; // 测试结果结构体 struct TestResult { - int totalQuestions; ///< 总问题数 - int correctAnswers; ///< 正确问题数 - double score; ///< 得分 + int total_questions; ///< 总问题数 + int correct_answers; ///< 正确问题数 + double score; ///< 得分 std::string difficulty; }; +// 验证码信息结构体 +struct VerificationCode { + std::string code; + std::time_t generate_time; + std::string email; +}; + +// 邮箱配置结构体 +struct EmailConfig { + std::string smtp_server = "smtp.163.com"; + int smtp_port = 25; + std::string username = "your_email@163.com"; + std::string password = "your_password"; + bool use_curl = true; // 使用libcurl发送邮件 +}; + // 前后端通信接口 class BackendInterface { -public: - /** - * @brief 请求发送验证码 - * @param email 邮箱地址 - * @return 发送成功true - */ - virtual bool sendSecondCode(const std::string& email) = 0; - - /** - * @brief 用户注册 - * @param user_name 用户名 - * @param password 密码 - * @param code 验证码 - * @return 注册成功true - */ - virtual bool userRegitster(const std::string& user_name, const std::string& password, const std::string& code) = 0; + public: + virtual ~BackendInterface() = default; - /** - * @brief 用户登陆 - * @param user_name 用户名 - * @param password 密码 - * @return 登陆成功true - */ - virtual bool userLogin(const std::string& user_name, const std::string& password) = 0; - virtual void userLogout() = 0; - virtual bool changePassword(const std::string& oldPassword, const std::string& newPassword) = 0; - virtual void userExit() = 0; - - /** - * @brief 题目生成 - * @param difficulty 题目难度(小学、初中、高中) - * @param count 题目数量 - * @return 返回生成的题目信息(采用QuestionInfor存储题目) - */ - virtual std::vector generateQuestions(const std::string& difficulty, int count) = 0; - - /** - * @brief 提交答案 - * @param userAnswers 0-3分别表示选项A-D - * @return 返回测试结果(采用TestResult存储测试结果) - */ - virtual TestResult submitAnswers(const std::vector& userAnswers) = 0; - - virtual ~BackendInterface() = default; + virtual bool SendVerificationCode(const std::string& email) = 0; + virtual bool UserRegister(const std::string& username, + const std::string& password, + const std::string& email, + const std::string& code) = 0; + virtual bool UserLogin(const std::string& username, + const std::string& password) = 0; + virtual void UserLogout() = 0; + virtual bool ChangePassword(const std::string& old_password, + const std::string& new_password) = 0; + virtual void UserExit() = 0; + virtual std::vector GenerateQuestions( + const std::string& difficulty, int count) = 0; + virtual TestResult SubmitAnswers(const std::vector& user_answers) = 0; + virtual std::string GetCurrentUser() const = 0; }; class BackendImpl : public BackendInterface { -public: - bool sendSecondCode(const std::string& email){ return true; }; - bool userRegitster(const std::string& user_name, const std::string& password, const std::string& code){ return true; }; - bool userLogin(const std::string& user_name, const std::string& password){ return true; }; - bool changePassword(const std::string& old_password, const std::string& new_password){ return true; }; - void userLogout(){return;}; - void userExit(){return;}; - std::vector generateQuestions(const std::string& difficulty, int count) { - std::vector questions = { - {1, "1 + 1 = ?", {"1", "2", "3", "4"}, 1}, - {2, "3 * 4 = ?", {"10", "12", "14", "16"}, 1}, - {3, "10 / 2 = ?", {"3", "4", "5", "6"}, 2}, - {4, "7 - 3 = ?", {"2", "3", "4", "5"}, 2}, - {5, "2 * 2 = ?", {"2", "3", "4", "5"}, 2}, - {6, "9 / 3 = ?", {"2", "3", "4", "5"}, 1}, - {7, "5 * 6 = ?", {"25", "30", "35", "40"}, 1}, - {8, "8 + 7 = ?", {"14", "15", "16", "17"}, 1}, - {9, "20 / 4 = ?", {"3", "4", "5", "6"}, 2}, - {10, "6 * 7 = ?", {"40", "42", "44", "46"}, 1} - }; - return questions; - } + public: + BackendImpl(); + ~BackendImpl() override = default; - TestResult submitAnswers(const std::vector& userAnswers){ - TestResult test_result = { - 10, - 8, - 80.0, - "小学" - }; + BackendImpl(const BackendImpl&) = delete; + BackendImpl& operator=(const BackendImpl&) = delete; - return test_result; - } + bool SendVerificationCode(const std::string& email) override; + bool UserRegister(const std::string& username, + const std::string& password, + const std::string& email, + const std::string& code) override; + bool UserLogin(const std::string& username, + const std::string& password) override; + void UserLogout() override; + bool ChangePassword(const std::string& old_password, + const std::string& new_password) override; + void UserExit() override; + std::vector GenerateQuestions( + const std::string& difficulty, int count) override; + TestResult SubmitAnswers(const std::vector& user_answers) override; + std::string GetCurrentUser() const override; - ~BackendImpl() = default ; + private: + // 邮件发送方法 + bool SendEmail(const std::string& recipient, + const std::string& subject, + const std::string& body); + bool SendEmailViaCurl(const std::string& recipient, + const std::string& subject, + const std::string& body); + + // 验证码管理 + std::string GenerateVerificationCode(); + bool ValidateVerificationCode(const std::string& email, + const std::string& code); + void CleanExpiredVerificationCodes(); + + // 题目生成辅助方法 + std::string CalculateSimpleAnswer(const std::string& problem); + std::vector GenerateOptions(const std::string& correct_answer); + double CalculateScore(int correct_count, int total_count); + + // 成员变量 + std::map verification_codes_; + std::map> user_questions_; + std::string current_user_; + std::vector current_correct_answers_; + std::unique_ptr exam_system_; + EmailConfig email_config_; }; +} // namespace exam_system -#endif \ No newline at end of file +#endif // BACKEND_INTERFACE_H \ No newline at end of file diff --git a/frontend/shared/output/backend_interface.exe b/frontend/shared/output/backend_interface.exe new file mode 100644 index 0000000..c014450 Binary files /dev/null and b/frontend/shared/output/backend_interface.exe differ diff --git a/src/exam_system/exam_system.h b/src/exam_system/exam_system.h index e38e66f..d1c45de 100644 --- a/src/exam_system/exam_system.h +++ b/src/exam_system/exam_system.h @@ -21,6 +21,7 @@ namespace constants { constexpr int kMinQuestionCount = 10; ///< 最小题目数量 constexpr int kMaxQuestionCount = 30; ///< 最大题目数量 constexpr int kExitCode = -1; ///< 退出代码 +constexpr char kDefaultUserDataFile[] = "users.csv"; ///< 默认用户数据文件名 } // namespace constants /** @@ -38,6 +39,7 @@ struct UserInfo { */ struct SystemConfig { std::vector users; ///< 系统用户列表 + std::string user_data_file; ///< 用户数据文件路径 }; /** @@ -76,18 +78,46 @@ struct LoginResponse { }; /** - * @brief 考试系统主类 + * @brief 修改密码请求 + */ +struct ChangePasswordRequest { + std::string username; ///< 用户名 + std::string old_password; ///< 旧密码 + std::string new_password; ///< 新密码 +}; + +/** + * @brief 修改密码响应 + */ +struct ChangePasswordResponse { + bool success; ///< 修改是否成功 + std::string error_message; ///< 错误信息 +}; + +/** + * @brief 考试系统控制层 * - * 管理整个系统的运行流程,包括用户登录、题目生成、文件保存等功能 + * 提供面向服务的API,处理业务逻辑,不直接处理用户交互 */ class ExamSystem { - public: + public: + /** + * @brief 默认构造函数 - 自动使用当前目录下的默认用户文件 + */ + ExamSystem(); + /** - * @brief 构造函数 + * @brief 构造函数 - 从配置对象初始化 * @param config 系统配置 */ explicit ExamSystem(const SystemConfig& config); + /** + * @brief 构造函数 - 从指定文件加载配置 + * @param config_file 配置文件路径 + */ + explicit ExamSystem(const std::string& config_file); + /// 析构函数 ~ExamSystem() = default; @@ -108,6 +138,13 @@ class ExamSystem { */ void Logout(const std::string& username); + /** + * @brief 修改密码 + * @param request 修改密码请求 + * @return 修改密码响应 + */ + ChangePasswordResponse ChangePassword(const ChangePasswordRequest& request); + /** * @brief 生成题目 * @param request 生成请求 @@ -166,113 +203,115 @@ class ExamSystem { * @return 是否有效 */ bool ValidateQuestionCount(int count) const; + /** - * @brief 运行系统主循环 - */ - void Run(); - - private: - /** - * @brief 初始化系统 + * @brief 保存用户数据到文件 + * @param file_path 文件路径,如果为空则使用配置中的路径 + * @return 保存是否成功 */ - void Initialize(); + bool SaveUserData(const std::string& file_path = ""); /** - * @brief 用户登录验证 - * @param username 用户名 - * @param password 密码 - * @return 登录成功返回true,否则返回false + * @brief 重新加载用户数据 + * @param file_path 文件路径,如果为空则使用配置中的路径 + * @return 加载是否成功 */ - bool Login(const std::string& username, const std::string& password); + bool ReloadUserData(const std::string& file_path = ""); /** - * @brief 设置题目生成器类型 - * @param type 生成器类型 - */ - void SetGenerator(const std::string& type); - /** - * @brief 设置题目生成器类型 - * @param username 用户名 - * @param type 生成器类型 + * @brief 获取用户数量 + * @return 用户数量 */ - void LoadUserHistory(const std::string& username); + size_t GetUserCount() const { return config_.users.size(); } /** - * @brief 获取用户生成器 - * @param username 用户名 - * @return 生成器指针,用户不存在返回nullptr + * @brief 获取当前登录用户数量 + * @return 登录用户数量 */ - ProblemGenerator* GetUserGenerator(const std::string& username); + size_t GetLoggedInUserCount() const { return user_sessions_.size(); } /** - * @brief 检查用户是否登录 - * @param username 用户名 - * @return 是否已登录 + * @brief 获取用户数据文件路径 + * @return 用户数据文件路径 */ - bool IsUserLoggedIn(const std::string& username) const; + std::string GetUserDataFilePath() const { return config_.user_data_file; } - SystemConfig config_; ///< 系统配置信息 - - // 用户会话数据 - struct UserSession { - std::unique_ptr generator; - std::string current_type; - bool history_loaded = false; - }; + private: + /** + * @brief 初始化系统 + */ + void Initialize(); - /** - * @brief 切换题目类型 - * @param type 要切换到的类型 + * @brief 初始化默认用户数据 */ - void SwitchType(const std::string& type); + void InitializeDefaultUsers(); /** - * @brief 生成指定数量的题目 - * @param count 题目数量 - * @return 题目列表 + * @brief 从文件加载用户数据 + * @param file_path 文件路径 + * @return 加载是否成功 */ - std::vector GenerateExam(int count); + bool LoadUserDataFromFile(const std::string& file_path); /** - * @brief 保存题目到文件 - * @param problems 题目列表 + * @brief 确保用户数据文件存在 + * @param file_path 文件路径 + * @return 文件存在或创建成功返回true */ - void SaveExam(const std::vector& problems); + bool EnsureUserDataFileExists(const std::string& file_path); /** - * @brief 处理用户输入 + * @brief 解析用户数据行 + * @param line 数据行 + * @param user_info 输出的用户信息 + * @return 解析是否成功 */ - void HandleUserInput(); + bool ParseUserDataLine(const std::string& line, UserInfo& user_info); /** - * @brief 显示登录提示 + * @brief 设置题目生成器类型 + * @param username 用户名 + * @param type 生成器类型 */ - void DisplayLoginPrompt(); + void SetGenerator(const std::string& username, const std::string& type); /** - * @brief 显示题目数量输入提示 + * @brief 加载用户历史题目 + * @param username 用户名 */ - void DisplayQuestionCountPrompt(); + void LoadUserHistory(const std::string& username); /** - * @brief 显示欢迎信息 + * @brief 获取用户生成器 + * @param username 用户名 + * @return 生成器指针,用户不存在返回nullptr */ - void DisplayWelcomeMessage(); + ProblemGenerator* GetUserGenerator(const std::string& username); /** - * @brief 用户登出 + * @brief 检查用户是否登录 + * @param username 用户名 + * @return 是否已登录 */ - void Logout(); - + bool IsUserLoggedIn(const std::string& username) const; + /** - * @brief 加载用户历史题目 + * @brief 更新用户密码 + * @param username 用户名 + * @param new_password 新密码 + * @return 更新是否成功 */ - void LoadUserHistory(); + bool UpdateUserPassword(const std::string& username, const std::string& new_password); + + // 用户会话数据 + struct UserSession { + std::unique_ptr generator; + std::string current_type; + bool history_loaded = false; + }; - SystemConfig config_; ///< 系统配置信息 - std::unique_ptr generator_; ///< 题目生成器实例 - const UserInfo* current_user_; ///< 当前登录用户指针 + SystemConfig config_; ///< 系统配置信息 std::map user_sessions_; ///< 用户会话映射 DuplicateChecker duplicate_checker_; ///< 查重服务实例 };