diff --git a/README.md b/README.md deleted file mode 100644 index 0f8dc2b..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# MathsQuestionSystem1 - diff --git a/doc/1.md b/doc/1.md new file mode 100644 index 0000000..12d1e93 --- /dev/null +++ b/doc/1.md @@ -0,0 +1,158 @@ +# 数学学习软件使用说明 + +## 项目概述 + +数学学习软件是一款专为不同学习阶段学生设计的数学练习工具,支持小学、初中和高中三个难度级别的数学题目练习。软件采用用户注册登录系统,通过邮箱验证确保用户身份安全。 + +## 系统要求 + +- **操作系统**: Windows 7及以上版本 +- **开发环境**: C++ (兼容C++98标准) +- **依赖组件**: + - Windows PowerShell (用于邮件发送) + - curl (可选,备用邮件发送方案) + +## 功能特点 + +### 1. 用户管理 +- **用户注册**: 通过邮箱验证码注册账号 +- **密码安全**: 密码要求6-10位,包含大小写字母和数字 +- **登录验证**: 安全的用户身份验证 + +### 2. 题目生成 +- **小学题目**: 基础四则运算,支持2-3个操作数 +- **初中题目**: 平方、开方运算 +- **高中题目**: 三角函数计算 + +### 3. 答题功能 +- **题目数量**: 可自定义10-30道题目 +- **实时反馈**: 即时显示答题结果 +- **进度跟踪**: 显示答题进度和得分 + +## 安装与配置 + +### 1. 编译说明 +项目使用标准C++编写,可在支持Windows API的开发环境中编译: +```bash +g++ -o MathLearning.exe *.cpp -luser32 -lgdi32 +``` + +### 2. 邮件配置 +如需使用邮件功能,需要配置QQ邮箱SMTP服务: + +1. 在 `EmailSender.cpp` 中修改发件人信息: +```cpp +const std::string sender_email = "your_email@qq.com"; +const std::string sender_password = "your_authorization_code"; +``` + +2. 获取QQ邮箱授权码: + - 登录QQ邮箱 → 设置 → 账户 + - 开启POP3/SMTP服务 + - 生成授权码 + +## 使用指南 + +### 1. 启动程序 +运行编译后的可执行文件,进入登录界面。 + +### 2. 用户注册 +1. 点击"注册"按钮 +2. 输入有效的邮箱地址 +3. 点击"获取验证码",查收邮件中的验证码 +4. 设置符合要求的密码(6-10位,包含大小写字母和数字) +5. 确认密码并完成注册 + +### 3. 用户登录 +1. 输入已注册的邮箱和密码 +2. 点击"登录"进入题目选择界面 + +### 4. 选择题目类型 +- **小学题目**: 适合小学生的基础数学运算 +- **初中题目**: 包含平方和开方运算 +- **高中题目**: 三角函数计算 + +### 5. 设置题目数量 +在10-30道题目范围内选择练习数量。 + +### 6. 答题界面 +- 阅读题目并选择正确答案 +- 点击"下一题"继续答题 +- 完成所有题目后查看成绩报告 + +## 文件结构 + +``` +项目根目录/ +├── main.cpp # 程序入口 +├── LoginWindow.h/cpp # 登录窗口 +├── RegisterWindow.h/cpp # 注册窗口 +├── SelectionWindow.h/cpp # 题目选择窗口 +├── QuestionWindow.h/cpp # 答题窗口 +├── User.h/cpp # 用户类 +├── UserManager.h/cpp # 用户管理 +├── Question.h/cpp # 题目类 +├── QuestionGenerator.h/cpp # 题目生成器 +├── EmailSender.h/cpp # 邮件发送器 +└── data/ + └── users.txt # 用户数据存储 +``` + +## 技术特性 + +### 1. 邮件发送 +- 支持PowerShell和curl两种发送方式 +- 自动故障转移机制 +- 详细的发送日志记录 + +### 2. 题目生成算法 +- 智能避免重复题目 +- 考虑运算优先级 +- 确保题目难度适中 + +### 3. 用户界面 +- 基于Windows API的本地化界面 +- 支持中文显示 +- 响应式窗口设计 + +## 故障排除 + +### 常见问题 + +1. **邮件发送失败** + - 检查邮箱配置是否正确 + - 确认网络连接正常 + - 查看email_send_log.txt日志文件 + +2. **程序无法启动** + - 确认系统满足要求 + - 检查依赖组件是否安装 + +3. **题目显示异常** + - 确保编译环境支持中文字符集 + - 检查控制台编码设置 + +### 日志文件 +程序生成以下日志文件用于故障诊断: +- `email_send_log.txt` - 邮件发送记录 +- 控制台输出 - 题目生成和答题详情 + +## 开发说明 + +### 扩展功能 +- 可添加更多题目类型 +- 支持用户成绩统计 +- 增加题目难度分级 + +### 自定义配置 +开发者可以通过修改相应头文件中的常量来调整: +- 题目数量范围 +- 密码复杂度要求 +- 邮件发送配置 + +## 版权信息 + +本软件为教育用途开发,遵循相关开源协议。 + +--- +*最后更新: 2024年* \ No newline at end of file diff --git a/src/EmailSender.cpp b/src/EmailSender.cpp new file mode 100644 index 0000000..4923474 --- /dev/null +++ b/src/EmailSender.cpp @@ -0,0 +1,217 @@ +#include "EmailSender.h" +#include +#include +#include +#include +#include + +bool EmailSender::sendVerificationCode(const std::string& email, const std::string& code) { + // ȳPowerShellʧ + std::cout << "=== ʼ֤ʼ ===" << std::endl; + std::cout << "ռ: " << email << std::endl; + std::cout << "֤: " << code << std::endl; + + // PowerShell + if (sendByPowerShell(email, code)) { + return true; + } + + std::cout << "PowerShellʧܣCURL..." << std::endl; + + // PowerShellʧܣCURL + if (sendByCurl(email, code)) { + return true; + } + + std::cout << "ʼͷʧ" << std::endl; + return false; +} + +bool EmailSender::sendByPowerShell(const std::string& email, const std::string& code) { + // ÷ͷϢ - ޸ΪʵϢ + const std::string sender_email = "3675658020@qq.com"; // ޸ΪQQ + const std::string sender_password = "lsagdbxwfolhcheb"; // ޸ΪQQȨ + + std::cout << "ʹPowerShellʼ..." << std::endl; + std::cout << ": " << sender_email << std::endl; + + // PowerShellű + std::string psScript = + "# ѧѧϰʼͽű\n" + "# \n" + "$SMTPServer = \"smtp.qq.com\"\n" + "$SMTPPort = \"587\"\n" + "$Username = \"" + sender_email + "\"\n" + "$Password = \"" + sender_password + "\"\n" + "$EmailFrom = \"" + sender_email + "\"\n" + "$EmailTo = \"" + email + "\"\n" + "$Subject = \"ѧѧϰ - ע֤\"\n" + "$Body = @\"\n" + "ӭעѧѧϰ\n" + "\n" + "ע֤ǣ" + code + "\n" + "\n" + "֤ЧΪ10ӣ뾡ʹá\n" + "\n" + "û֤룬Դʼ\n" + "\n" + "лл\n" + "ѧѧϰŶ\n" + "\"@\n" + "\n" + "Write-Host \"ڷʼ: $EmailTo\"\n" + "Write-Host \"֤: " + code + "\"\n" + "\n" + "try {\n" + " # ʼϢ\n" + " $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body)\n" + " \n" + " # SMTPͻ\n" + " $SMTPClient = New-Object Net.Mail.SmtpClient($SMTPServer, $SMTPPort)\n" + " $SMTPClient.EnableSsl = $true\n" + " $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)\n" + " \n" + " # ʼ\n" + " $SMTPClient.Send($SMTPMessage)\n" + " \n" + " Write-Host \"ʼͳɹ\" -ForegroundColor Green\n" + " Write-Output \"SUCCESS\"\n" + " \n" + "} catch {\n" + " Write-Host \"ʼʧ: $($_.Exception.Message)\" -ForegroundColor Red\n" + " Write-Output \"ERROR: $($_.Exception.Message)\"\n" + "}"; + + // PowerShellű + std::ofstream scriptFile("send_email.ps1"); + if (!scriptFile) { + std::cout << "PowerShellűļʧ" << std::endl; + return false; + } + scriptFile << psScript; + scriptFile.close(); + + std::cout << "ִPowerShellű..." << std::endl; + + // ִPowerShellű + std::string command = "powershell -ExecutionPolicy Bypass -File send_email.ps1"; + FILE* pipe = _popen(command.c_str(), "r"); + if (!pipe) { + std::cout << "ִPowerShellʧ" << std::endl; + return false; + } + + char buffer[256]; + std::string result = ""; + while (!feof(pipe)) { + if (fgets(buffer, sizeof(buffer), pipe) != NULL) + result += buffer; + } + _pclose(pipe); + + // ¼־ + std::ofstream logFile("email_send_log.txt", std::ios::app); + if (logFile) { + logFile << "=== ʼͼ¼ ===" << std::endl; + logFile << "ʱ: " << __DATE__ << " " << __TIME__ << std::endl; + logFile << ": PowerShell" << std::endl; + logFile << ": " << sender_email << std::endl; + logFile << "ռ: " << email << std::endl; + logFile << "֤: " << code << std::endl; + logFile << "ִн: " << result << std::endl; + logFile << "=========================" << std::endl << std::endl; + logFile.close(); + } + + // ִн + if (result.find("SUCCESS") != std::string::npos) { + std::cout << "? ʼͳɹ" << std::endl; + std::cout << "֤ѷ͵: " << email << std::endl; + return true; + } else { + std::cout << "? PowerShellʧ: " << result << std::endl; + return false; + } +} + +bool EmailSender::sendByCurl(const std::string& email, const std::string& code) { + // ÷ͷϢ - ޸ΪʵϢ + const std::string sender_email = "3675658020@qq.com"; // ޸ΪQQ + const std::string sender_password = "lsagdbxwfolhcheb"; // ޸ΪQQȨ + + std::cout << "ʹCURLʼ..." << std::endl; + + // ϵͳǷװcurl + int curlCheck = system("curl --version > nul 2>&1"); + if (curlCheck != 0) { + std::cout << "ϵͳδװcurl˷" << std::endl; + return false; + } + + std::cout << "⵽curlʼ..." << std::endl; + + // ʼļ + std::ofstream mailFile("email_content.txt"); + if (!mailFile) { + std::cout << "ʼļʧ" << std::endl; + return false; + } + + mailFile << "From: ѧѧϰ <" << sender_email << ">\n"; + mailFile << "To: " << email << "\n"; + mailFile << "Subject: ѧѧϰ - ע֤\n"; + mailFile << "Content-Type: text/plain; charset=\"utf-8\"\n"; + mailFile << "\n"; + mailFile << "ӭעѧѧϰ\n"; + mailFile << "\n"; + mailFile << "ע֤ǣ" << code << "\n"; + mailFile << "\n"; + mailFile << "֤ЧΪ10ӣ뾡ʹá\n"; + mailFile << "\n"; + mailFile << "û֤룬Դʼ\n"; + mailFile << "\n"; + mailFile << "лл\n"; + mailFile << "ѧѧϰŶ\n"; + mailFile.close(); + + // ʹcurlʼ + std::string curlCommand = + "curl -s --url \"smtp://smtp.qq.com:587\" " + "--ssl-reqd " + "--mail-from \"" + sender_email + "\" " + "--mail-rcpt \"" + email + "\" " + "--user \"" + sender_email + ":" + sender_password + "\" " + "--upload-file email_content.txt " + "> curl_output.txt 2>&1"; + + std::cout << "ִCURL..." << std::endl; + int result = system(curlCommand.c_str()); + + // ¼־ + std::ofstream logFile("email_send_log.txt", std::ios::app); + if (logFile) { + logFile << "=== CURLʼͼ¼ ===" << std::endl; + logFile << "ʱ: " << __DATE__ << " " << __TIME__ << std::endl; + logFile << ": CURL" << std::endl; + logFile << ": " << sender_email << std::endl; + logFile << "ռ: " << email << std::endl; + logFile << "֤: " << code << std::endl; + logFile << ": " << result << std::endl; + logFile << "=========================" << std::endl << std::endl; + logFile.close(); + } + + if (result == 0) { + std::cout << "? CURLʼͳɹ" << std::endl; + return true; + } else { + std::cout << "? CURLʼʧܣ: " << result << std::endl; + return false; + } +} + +bool EmailSender::sendBySMTP(const std::string& email, const std::string& code) { + // Ϊ÷ǰʹ + std::cout << "SMTPݲ" << std::endl; + return false; +} diff --git a/src/EmailSender.h b/src/EmailSender.h new file mode 100644 index 0000000..f9e0d17 --- /dev/null +++ b/src/EmailSender.h @@ -0,0 +1,16 @@ +#ifndef EMAILSENDER_H +#define EMAILSENDER_H + +#include + +class EmailSender { +public: + static bool sendVerificationCode(const std::string& email, const std::string& code); + +private: + static bool sendByPowerShell(const std::string& email, const std::string& code); + static bool sendByCurl(const std::string& email, const std::string& code); + static bool sendBySMTP(const std::string& email, const std::string& code); +}; + +#endif diff --git a/src/EmailSender.o b/src/EmailSender.o new file mode 100644 index 0000000..cc55a0e Binary files /dev/null and b/src/EmailSender.o differ diff --git a/src/LoginWindow.cpp b/src/LoginWindow.cpp new file mode 100644 index 0000000..34b51c3 --- /dev/null +++ b/src/LoginWindow.cpp @@ -0,0 +1,135 @@ +#include "LoginWindow.h" +#include "UserManager.h" +#include "RegisterWindow.h" +#include "SelectionWindow.h" +#include +#include + +HWND LoginWindow::hwnd = NULL; +HWND LoginWindow::hEmail = NULL; +HWND LoginWindow::hPassword = NULL; +HWND LoginWindow::hMessage = NULL; + +void LoginWindow::Show() { + // Ѵڣ + if (hwnd != NULL) { + DestroyWindow(hwnd); + hwnd = NULL; + } + + WNDCLASSEX wc; + memset(&wc, 0, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszClassName = "LoginWindow"; + + RegisterClassEx(&wc); + + hwnd = CreateWindowEx(0, "LoginWindow", "ѧѧϰ - ¼", + WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, + NULL, NULL, GetModuleHandle(NULL), NULL); + + if (!hwnd) { + MessageBox(NULL, "¼ʧ", "", MB_OK | MB_ICONERROR); + return; + } + + CreateControls(); + + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); +} + +void LoginWindow::CreateControls() { + // + CreateWindow("STATIC", "ѧѧϰ", WS_VISIBLE | WS_CHILD | SS_CENTER, + 10, 20, 360, 30, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ǩ + CreateWindow("STATIC", ":", WS_VISIBLE | WS_CHILD, + 50, 70, 50, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hEmail = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER, + 100, 70, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ǩ + CreateWindow("STATIC", ":", WS_VISIBLE | WS_CHILD, + 50, 110, 50, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hPassword = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_PASSWORD, + 100, 110, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ¼ť + CreateWindow("BUTTON", "¼", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 100, 150, 80, 30, hwnd, (HMENU)1, GetModuleHandle(NULL), NULL); + + // עᰴť + CreateWindow("BUTTON", "ע", WS_VISIBLE | WS_CHILD, + 200, 150, 80, 30, hwnd, (HMENU)2, GetModuleHandle(NULL), NULL); + + // Ϣǩ - ޸ WM_CHILD Ϊ WS_CHILD + hMessage = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_CENTER, + 50, 190, 300, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); +} + +LRESULT CALLBACK LoginWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_COMMAND: { + int cmd = LOWORD(wParam); + if (cmd == 1) { // ¼ť + OnLogin(); + } else if (cmd == 2) { // עᰴť + OnRegister(); + } + break; + } + case WM_CLOSE: + DestroyWindow(hwnd); + PostQuitMessage(0); // ֻйرյ¼ʱ˳ + break; + case WM_DESTROY: + // WM_DESTROYеPostQuitMessage˳ + break; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +void LoginWindow::OnLogin() { + char email[100], password[100]; + GetWindowText(hEmail, email, sizeof(email)); + GetWindowText(hPassword, password, sizeof(password)); + + std::string strEmail(email); + std::string strPassword(password); + + if (strEmail.empty() || strPassword.empty()) { + SetWindowText(hMessage, ""); + return; + } + + UserManager& userManager = UserManager::getInstance(); + if (userManager.login(strEmail, strPassword)) { + SetWindowText(hMessage, "¼ɹ"); + + // ӳٺлѡ + Sleep(800); + DestroyWindow(hwnd); + hwnd = NULL; // ôھ + + // ʾѡ + SelectionWindow::Show(); + } else { + SetWindowText(hMessage, "¼ʧܣ"); + } +} + +void LoginWindow::OnRegister() { + DestroyWindow(hwnd); + hwnd = NULL; + RegisterWindow::Show(); +} diff --git a/src/LoginWindow.h b/src/LoginWindow.h new file mode 100644 index 0000000..7660549 --- /dev/null +++ b/src/LoginWindow.h @@ -0,0 +1,23 @@ +#ifndef LOGINWINDOW_H +#define LOGINWINDOW_H + +#include + +class LoginWindow { +public: + static void Show(); + static HWND GetHandle() { return hwnd; } + +private: + static HWND hwnd; + static HWND hEmail; + static HWND hPassword; + static HWND hMessage; + + static void CreateControls(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static void OnLogin(); + static void OnRegister(); +}; + +#endif diff --git a/src/LoginWindow.o b/src/LoginWindow.o new file mode 100644 index 0000000..7b64bcd Binary files /dev/null and b/src/LoginWindow.o differ diff --git a/src/Makefile.win b/src/Makefile.win new file mode 100644 index 0000000..e043d3f --- /dev/null +++ b/src/Makefile.win @@ -0,0 +1,55 @@ +# Project: Ŀ1 +# Makefile created by Dev-C++ 5.11 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +OBJ = UserManager.o User.o QuestionGenerator.o Question.o LoginWindow.o RegisterWindow.o QuestionWindow.o main.o EmailSender.o SelectionWindow.o +LINKOBJ = UserManager.o User.o QuestionGenerator.o Question.o LoginWindow.o RegisterWindow.o QuestionWindow.o main.o EmailSender.o SelectionWindow.o +LIBS = -L"D://Dev-Cpp/MinGW64/lib" -L"D://Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib" -static-libgcc -mwindows -lws2_32 -lwininet +INCS = -I"D://Dev-Cpp/MinGW64/include" -I"D://Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"D://Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" +CXXINCS = -I"D://Dev-Cpp/MinGW64/include" -I"D://Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"D://Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"D://Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++" +BIN = test3.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) +RM = rm.exe -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +UserManager.o: UserManager.cpp + $(CPP) -c UserManager.cpp -o UserManager.o $(CXXFLAGS) + +User.o: User.cpp + $(CPP) -c User.cpp -o User.o $(CXXFLAGS) + +QuestionGenerator.o: QuestionGenerator.cpp + $(CPP) -c QuestionGenerator.cpp -o QuestionGenerator.o $(CXXFLAGS) + +Question.o: Question.cpp + $(CPP) -c Question.cpp -o Question.o $(CXXFLAGS) + +LoginWindow.o: LoginWindow.cpp + $(CPP) -c LoginWindow.cpp -o LoginWindow.o $(CXXFLAGS) + +RegisterWindow.o: RegisterWindow.cpp + $(CPP) -c RegisterWindow.cpp -o RegisterWindow.o $(CXXFLAGS) + +QuestionWindow.o: QuestionWindow.cpp + $(CPP) -c QuestionWindow.cpp -o QuestionWindow.o $(CXXFLAGS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +EmailSender.o: EmailSender.cpp + $(CPP) -c EmailSender.cpp -o EmailSender.o $(CXXFLAGS) + +SelectionWindow.o: SelectionWindow.cpp + $(CPP) -c SelectionWindow.cpp -o SelectionWindow.o $(CXXFLAGS) diff --git a/src/Question.cpp b/src/Question.cpp new file mode 100644 index 0000000..28a30cb --- /dev/null +++ b/src/Question.cpp @@ -0,0 +1,27 @@ +#include "Question.h" + +Question::Question(const std::string& text, const std::vector& options, int correctAnswer) + : text(text), options(options), correctAnswer(correctAnswer) {} + +std::string Question::getText() const { + return text; +} + +std::vector Question::getOptions() const { + return options; +} + +int Question::getCorrectAnswer() const { + return correctAnswer; +} + +bool Question::checkAnswer(int userAnswer) const { + return userAnswer == correctAnswer; +} + +std::string Question::getCorrectOptionText() const { + if (correctAnswer >= 0 && correctAnswer < (int)options.size()) { + return options[correctAnswer]; + } + return "ȷ"; +} diff --git a/src/Question.h b/src/Question.h new file mode 100644 index 0000000..b97684e --- /dev/null +++ b/src/Question.h @@ -0,0 +1,25 @@ +#ifndef QUESTION_H +#define QUESTION_H + +#include +#include + +class Question { +public: + Question(const std::string& text, const std::vector& options, int correctAnswer); + + std::string getText() const; + std::vector getOptions() const; + int getCorrectAnswer() const; + bool checkAnswer(int userAnswer) const; + + // ӵԷ + std::string getCorrectOptionText() const; + +private: + std::string text; + std::vector options; + int correctAnswer; +}; + +#endif diff --git a/src/Question.o b/src/Question.o new file mode 100644 index 0000000..fd3d72a Binary files /dev/null and b/src/Question.o differ diff --git a/src/QuestionGenerator.cpp b/src/QuestionGenerator.cpp new file mode 100644 index 0000000..b2b9bb0 --- /dev/null +++ b/src/QuestionGenerator.cpp @@ -0,0 +1,442 @@ +#include "QuestionGenerator.h" +#include "Question.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// C++98ݵתַ +std::string intToString(int value) { + std::stringstream ss; + ss << value; + return ss.str(); +} + +// תַ2λС +std::string doubleToString(double value) { + std::stringstream ss; + ss.precision(2); + ss << std::fixed << value; + return ss.str(); +} + +QuestionGenerator::QuestionGenerator(const std::string& userType) : userType(userType) { + srand(static_cast(time(NULL))); +} + +std::vector QuestionGenerator::generateQuestions(int count) { + std::vector questions; + + for (int i = 0; i < count; ++i) { + Question question("", std::vector(), 0); + + if (userType == "elementary") { + question = generateElementaryQuestion(); + } else if (userType == "middle") { + question = generateMiddleSchoolQuestion(); + } else if (userType == "high") { + question = generateHighSchoolQuestion(); + } + + if (question.getText() != "" && question.getOptions().size() == 4) { + questions.push_back(question); + } else { + // ʧܣ + i--; + } + } + + return questions; +} + +// ȡȼ +int getOperatorPriority(char op) { + if (op == '*' || op == '/') return 2; + if (op == '+' || op == '-') return 1; + return 0; +} + +// +int calculate(int a, int b, char op) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': + if (b != 0 && a % b == 0) return a / b; + return a; // ԭֵӦòᷢ + default: return a; + } +} + +// ʹջʽȷȼ +int calculateWithPriority(const std::vector& numbers, const std::vector& operators) { + if (numbers.size() != operators.size() + 1) { + return numbers[0]; // صһ + } + + std::stack numStack; + std::stack opStack; + + numStack.push(numbers[0]); + + for (size_t i = 0; i < operators.size(); ++i) { + char currentOp = operators[i]; + int currentNum = numbers[i + 1]; + + // ȼ + while (!opStack.empty() && getOperatorPriority(opStack.top()) >= getOperatorPriority(currentOp)) { + int num2 = numStack.top(); numStack.pop(); + int num1 = numStack.top(); numStack.pop(); + char op = opStack.top(); opStack.pop(); + numStack.push(calculate(num1, num2, op)); + } + + opStack.push(currentOp); + numStack.push(currentNum); + } + + // ʣIJ + while (!opStack.empty()) { + int num2 = numStack.top(); numStack.pop(); + int num1 = numStack.top(); numStack.pop(); + char op = opStack.top(); opStack.pop(); + numStack.push(calculate(num1, num2, op)); + } + + return numStack.top(); +} + +// ɱʽַʾȼ +std::string generateExpressionString(const std::vector& numbers, const std::vector& operators) { + std::string expression = intToString(numbers[0]); + + for (size_t i = 0; i < operators.size(); ++i) { + expression += " "; + expression += operators[i]; + expression += " "; + expression += intToString(numbers[i + 1]); + } + + return expression; +} + +Question QuestionGenerator::generateElementaryQuestion() { + int operandCount = 2 + rand() % 2; // 2-3 + + std::vector numbers; + std::vector operators; + + // ɵһ + numbers.push_back(1 + rand() % 20); + + // ɲ + for (int i = 0; i < operandCount; ++i) { + char op; + int num = 1 + rand() % 15; + + // ѡ + if (i == 0) { + // һѡ + op = "+-*/"[rand() % 4]; + } else { + // ⸴ + if (operators[i-1] == '*' || operators[i-1] == '/') { + op = "+-"[rand() % 2]; // ˳ӼӼ + } else { + op = "+-*/"[rand() % 4]; + } + } + + // ⴦ + if (op == '/') { + // ȷ + if (num == 0) num = 1; + // ȷ + numbers[i] = numbers[i] * num; + } else if (op == '-') { + // ȷΪ + // ȼ㵱ǰֵ + int currentValue = calculateWithPriority(numbers, operators); + if (currentValue - num < 0) { + num = rand() % currentValue + 1; + } + } else if (op == '*') { + // + if (numbers[i] * num > 100) { + num = 2; + } + } + + operators.push_back(op); + numbers.push_back(num); + } + + // ȷ + int result = calculateWithPriority(numbers, operators); + + // ȷ + if (result <= 0 || result > 200) { + return generateElementaryQuestion(); // + } + + // ɱʽ + std::string expression = generateExpressionString(numbers, operators); + std::string questionText = expression + " = ?"; + + if (isDuplicate(questionText)) { + return generateElementaryQuestion(); + } + + addToHistory(questionText); + + // ѡ + std::vector options; + int correctIndex = rand() % 4; + + // 3 + std::vector wrongAnswers; + for (int i = 0; i < 3; ++i) { + int wrongAnswer; + int attempts = 0; + do { + attempts++; + if (attempts > 10) { + wrongAnswer = result + (i + 1) * 3; + break; + } + + int offset = (rand() % 10) + 2; + if (rand() % 2 == 0) { + wrongAnswer = result + offset; + } else { + wrongAnswer = result - offset; + if (wrongAnswer < 1) wrongAnswer = result + offset; + } + } while (wrongAnswer == result || + std::find(wrongAnswers.begin(), wrongAnswers.end(), wrongAnswer) != wrongAnswers.end()); + + wrongAnswers.push_back(wrongAnswer); + } + + // ѡ + for (int i = 0; i < 4; ++i) { + if (i == correctIndex) { + options.push_back(intToString(result)); + } else { + options.push_back(intToString(wrongAnswers[i > correctIndex ? i-1 : i])); + } + } + + // + std::cout << "СѧĿ: " << questionText << std::endl; + std::cout << "˳: "; + for (size_t i = 0; i < numbers.size(); ++i) { + std::cout << numbers[i]; + if (i < operators.size()) { + std::cout << " " << operators[i] << " "; + } + } + std::cout << " = " << result << std::endl; + std::cout << "ȷ: " << result << std::endl; + std::cout << "------------------------" << std::endl; + + return Question(questionText, options, correctIndex); +} + +// ҵһԼ +int QuestionGenerator::findDivisor(int number) { + if (number <= 1) return 1; + + for (int i = 2; i <= 10; ++i) { + if (number % i == 0) { + return i; + } + } + + return 1; +} +Question QuestionGenerator::generateMiddleSchoolQuestion() { + int type = rand() % 2; // 0: ƽ, 1: + + if (type == 0) { + // ƽ + int base = 2 + rand() % 15; // 2-16 + int coefficient = 1 + rand() % 5; + int result = coefficient * base * base; + + std::string questionText; + if (coefficient == 1) { + // 1: ʹUnicodeϱ + // questionText = intToString(base) + "2 = ?"; + + // 2: ʹı + questionText = intToString(base) + "ƽ = ?"; + } else { + // questionText = intToString(coefficient) + " " + intToString(base) + "2 = ?"; + questionText = intToString(coefficient) + " " + intToString(base) + "ƽ = ?"; + } + + if (isDuplicate(questionText)) { + return generateMiddleSchoolQuestion(); + } + + addToHistory(questionText); + + // ѡ + std::vector options; + int correctIndex = rand() % 4; + + std::vector wrongAnswers; + for (int i = 0; i < 3; ++i) { + int wrongAnswer; + do { + int offset = (rand() % 20) + 5; + if (rand() % 2 == 0) { + wrongAnswer = result + offset; + } else { + wrongAnswer = result - offset; + if (wrongAnswer <= 0) wrongAnswer = result + offset; + } + } while (wrongAnswer == result || + std::find(wrongAnswers.begin(), wrongAnswers.end(), wrongAnswer) != wrongAnswers.end()); + + wrongAnswers.push_back(wrongAnswer); + } + + for (int i = 0; i < 4; ++i) { + if (i == correctIndex) { + options.push_back(intToString(result)); + } else { + options.push_back(intToString(wrongAnswers[i > correctIndex ? i-1 : i])); + } + } + + return Question(questionText, options, correctIndex); + } else { + // + int base = 2 + rand() % 12; // 2-13 + int squared = base * base; + + // 1: ʹUnicodeƽ + // std::string questionText = "(" + intToString(squared) + ") = ?"; + + // 2: ʹı + std::string questionText = "" + intToString(squared) + " = ?"; + + if (isDuplicate(questionText)) { + return generateMiddleSchoolQuestion(); + } + + addToHistory(questionText); + + // ѡ + std::vector options; + int correctIndex = rand() % 4; + + std::vector wrongAnswers; + for (int i = 0; i < 3; ++i) { + int wrongAnswer; + do { + wrongAnswer = base + (rand() % 5) - 2; // -2+2ƫ + if (wrongAnswer <= 0) wrongAnswer = 1; + } while (wrongAnswer == base || + std::find(wrongAnswers.begin(), wrongAnswers.end(), wrongAnswer) != wrongAnswers.end()); + + wrongAnswers.push_back(wrongAnswer); + } + + for (int i = 0; i < 4; ++i) { + if (i == correctIndex) { + options.push_back(intToString(base)); + } else { + options.push_back(intToString(wrongAnswers[i > correctIndex ? i-1 : i])); + } + } + + return Question(questionText, options, correctIndex); + } +} +Question QuestionGenerator::generateHighSchoolQuestion() { + const char* trigFunctions[] = {"sin", "cos", "tan"}; + const char* currentFunc = trigFunctions[rand() % 3]; + int angle = 0; + double result = 0.0; + + int commonAngles[] = {0, 30, 45, 60, 90}; + angle = commonAngles[rand() % 5]; + + double radian = angle * 3.14159 / 180.0; + if (std::string(currentFunc) == "sin") { + result = sin(radian); + } else if (std::string(currentFunc) == "cos") { + result = cos(radian); + } else { + if (angle == 90) angle = 45; + radian = angle * 3.14159 / 180.0; + result = tan(radian); + } + + result = round(result * 100) / 100.0; + + std::string questionText = std::string(currentFunc) + "(" + intToString(angle) + ") = ?"; + + if (isDuplicate(questionText)) { + return generateHighSchoolQuestion(); + } + + addToHistory(questionText); + + std::vector options; + int correctIndex = rand() % 4; + + std::vector wrongAnswers; + for (int i = 0; i < 3; ++i) { + double wrongAnswer; + do { + double offset = (rand() % 20 + 5) / 100.0; + if (rand() % 2 == 0) { + wrongAnswer = result + offset; + } else { + wrongAnswer = result - offset; + if (wrongAnswer < -1.0) wrongAnswer = result + offset; + } + wrongAnswer = round(wrongAnswer * 100) / 100.0; + } while (wrongAnswer == result || + std::find(wrongAnswers.begin(), wrongAnswers.end(), wrongAnswer) != wrongAnswers.end()); + + wrongAnswers.push_back(wrongAnswer); + } + + for (int i = 0; i < 4; ++i) { + if (i == correctIndex) { + options.push_back(doubleToString(result)); + } else { + options.push_back(doubleToString(wrongAnswers[i > correctIndex ? i-1 : i])); + } + } + + return Question(questionText, options, correctIndex); +} + +bool QuestionGenerator::isDuplicate(const std::string& questionText) { + for (std::set::iterator it = questionHistory.begin(); it != questionHistory.end(); ++it) { + if (*it == questionText) { + return true; + } + } + return false; +} + +void QuestionGenerator::addToHistory(const std::string& questionText) { + questionHistory.insert(questionText); +} + +void QuestionGenerator::clearHistory() { + questionHistory.clear(); +} diff --git a/src/QuestionGenerator.h b/src/QuestionGenerator.h new file mode 100644 index 0000000..c15e604 --- /dev/null +++ b/src/QuestionGenerator.h @@ -0,0 +1,29 @@ +#ifndef QUESTIONGENERATOR_H +#define QUESTIONGENERATOR_H + +#include "Question.h" +#include +#include +#include + +class QuestionGenerator { +public: + QuestionGenerator(const std::string& userType); + + std::vector generateQuestions(int count); + void clearHistory(); + +private: + std::string userType; + std::set questionHistory; + + Question generateElementaryQuestion(); + Question generateMiddleSchoolQuestion(); + Question generateHighSchoolQuestion(); + + int findDivisor(int number); + bool isDuplicate(const std::string& questionText); + void addToHistory(const std::string& questionText); +}; + +#endif diff --git a/src/QuestionGenerator.o b/src/QuestionGenerator.o new file mode 100644 index 0000000..0247ebc Binary files /dev/null and b/src/QuestionGenerator.o differ diff --git a/src/QuestionWindow.cpp b/src/QuestionWindow.cpp new file mode 100644 index 0000000..f7f5aef --- /dev/null +++ b/src/QuestionWindow.cpp @@ -0,0 +1,195 @@ +#include "QuestionWindow.h" +#include "QuestionGenerator.h" +#include "SelectionWindow.h" +#include +#include +#include +#include // iostreamڵ + +HWND QuestionWindow::hwnd = NULL; +HWND QuestionWindow::hQuestionText = NULL; +HWND QuestionWindow::hOptions[4] = {NULL, NULL, NULL, NULL}; +HWND QuestionWindow::hNextButton = NULL; +HWND QuestionWindow::hProgress = NULL; + +std::vector QuestionWindow::questions; +int QuestionWindow::currentQuestion = 0; +int QuestionWindow::score = 0; + +void QuestionWindow::Show(const std::string& userType, int questionCount) { + // Ѵڣ + if (hwnd != NULL) { + DestroyWindow(hwnd); + hwnd = NULL; + } + + // Ŀ - ʹôĿ + QuestionGenerator generator(userType); + questions = generator.generateQuestions(questionCount); + currentQuestion = 0; + score = 0; + + WNDCLASSEX wc; + memset(&wc, 0, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszClassName = "QuestionWindow"; + + RegisterClassEx(&wc); + + hwnd = CreateWindowEx(0, "QuestionWindow", "ѧѧϰ - ", + WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 500, 400, + NULL, NULL, GetModuleHandle(NULL), NULL); + + if (!hwnd) { + MessageBox(NULL, "ⴰʧ", "", MB_OK | MB_ICONERROR); + return; + } + + CreateControls(); + LoadQuestion(); + + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); +} + +void QuestionWindow::CreateControls() { + // ʾ + hProgress = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_LEFT, + 10, 10, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // Ŀı + hQuestionText = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_LEFT | WS_BORDER, + 10, 50, 460, 60, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ѡť + for (int i = 0; i < 4; i++) { + hOptions[i] = CreateWindow("BUTTON", "", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + 10, 120 + i * 40, 460, 30, hwnd, (HMENU)(10 + i), + GetModuleHandle(NULL), NULL); + } + + // һⰴť + hNextButton = CreateWindow("BUTTON", "һ", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 200, 300, 100, 30, hwnd, (HMENU)20, GetModuleHandle(NULL), NULL); +} + +LRESULT CALLBACK QuestionWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_COMMAND: { + int cmd = LOWORD(wParam); + if (cmd == 20) { // һⰴť + OnNextQuestion(); + } + break; + } + case WM_CLOSE: + DestroyWindow(hwnd); + SelectionWindow::Show(); // رʱѡ + break; + case WM_DESTROY: + break; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +void QuestionWindow::LoadQuestion() { + if (currentQuestion >= (int)questions.size()) { + ShowResult(); + return; + } + + Question& question = questions[currentQuestion]; + + // ½ + std::stringstream progress; + progress << ": " << (currentQuestion + 1) << "/" << questions.size(); + SetWindowText(hProgress, progress.str().c_str()); + + // Ŀı + SetWindowText(hQuestionText, question.getText().c_str()); + + // ѡ + std::vector options = question.getOptions(); + + // ʾȷ𰸣ڿ̨ + std::cout << "Ŀ " << (currentQuestion + 1) << ": " << question.getText() << std::endl; + std::cout << "ȷ: ѡ" << (question.getCorrectAnswer() + 1) + << " - " << options[question.getCorrectAnswer()] << std::endl; + std::cout << "ѡ: "; + for (int i = 0; i < 4; i++) { + std::cout << "[" << (i+1) << "]" << options[i] << " "; + } + std::cout << std::endl << std::endl; + + for (int i = 0; i < 4; i++) { + if (i < (int)options.size()) { + SetWindowText(hOptions[i], options[i].c_str()); + } + SendMessage(hOptions[i], BM_SETCHECK, BST_UNCHECKED, 0); + } + + if (currentQuestion == (int)questions.size() - 1) { + SetWindowText(hNextButton, "ύ"); + } +} + +void QuestionWindow::OnNextQuestion() { + // 鵱ǰѡĴ + int selectedAnswer = -1; + for (int i = 0; i < 4; i++) { + if (SendMessage(hOptions[i], BM_GETCHECK, 0, 0) == BST_CHECKED) { + selectedAnswer = i; + break; + } + } + + if (selectedAnswer == -1) { + MessageBox(hwnd, "ѡһ", "ʾ", MB_OK | MB_ICONINFORMATION); + return; + } + + // + if (questions[currentQuestion].checkAnswer(selectedAnswer)) { + score++; + std::cout << "" << (currentQuestion + 1) << "شȷ" << std::endl; + } else { + std::cout << "" << (currentQuestion + 1) << "ش" << std::endl; + } + + currentQuestion++; + LoadQuestion(); +} +void QuestionWindow::ShowResult() { + std::stringstream result; + int total = questions.size(); + int percentage = (total > 0) ? (score * 100 / total) : 0; + + result << "ɣ\n÷: " << score << "/" << total + << "\nȷ: " << percentage << "%\n\n" + << "ѡ\n" + << " - ѡ\n" + << " - "; + + // ʾѡϢ + int choice = MessageBox(hwnd, result.str().c_str(), "", + MB_YESNO | MB_ICONINFORMATION | MB_DEFBUTTON1); + + DestroyWindow(hwnd); + hwnd = NULL; + + if (choice == IDYES) { + // ûѡ"" - ⣬ѡ + SelectionWindow::Show(); + } else { + // ûѡ"" - ˳ + PostQuitMessage(0); + } +} diff --git a/src/QuestionWindow.h b/src/QuestionWindow.h new file mode 100644 index 0000000..30322ee --- /dev/null +++ b/src/QuestionWindow.h @@ -0,0 +1,32 @@ +#ifndef QUESTIONWINDOW_H +#define QUESTIONWINDOW_H + +#include +#include +#include +#include "Question.h" + +class QuestionWindow { +public: + static void Show(const std::string& userType, int questionCount); + static HWND GetHandle() { return hwnd; } + +private: + static HWND hwnd; + static HWND hQuestionText; + static HWND hOptions[4]; + static HWND hNextButton; + static HWND hProgress; + + static std::vector questions; + static int currentQuestion; + static int score; + + static void CreateControls(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static void LoadQuestion(); + static void OnNextQuestion(); + static void ShowResult(); +}; + +#endif diff --git a/src/QuestionWindow.o b/src/QuestionWindow.o new file mode 100644 index 0000000..8c96738 Binary files /dev/null and b/src/QuestionWindow.o differ diff --git a/src/RegisterWindow.cpp b/src/RegisterWindow.cpp new file mode 100644 index 0000000..a92f1ca --- /dev/null +++ b/src/RegisterWindow.cpp @@ -0,0 +1,225 @@ +#include "RegisterWindow.h" +#include "UserManager.h" +#include "LoginWindow.h" +#include +#include +#include + +HWND RegisterWindow::hwnd = NULL; +HWND RegisterWindow::hEmail = NULL; +HWND RegisterWindow::hCode = NULL; +HWND RegisterWindow::hPassword = NULL; +HWND RegisterWindow::hConfirmPassword = NULL; +HWND RegisterWindow::hMessage = NULL; +std::string RegisterWindow::generatedCode = ""; + +void RegisterWindow::Show() { + // Ѵڣ + if (hwnd != NULL) { + DestroyWindow(hwnd); + hwnd = NULL; + } + + WNDCLASSEX wc; + memset(&wc, 0, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszClassName = "RegisterWindow"; + + RegisterClassEx(&wc); + + hwnd = CreateWindowEx(0, "RegisterWindow", "ѧѧϰ - ע", + WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 400, 450, + NULL, NULL, GetModuleHandle(NULL), NULL); + + if (!hwnd) { + MessageBox(NULL, "עᴰʧ", "", MB_OK | MB_ICONERROR); + return; + } + + CreateControls(); + + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); +} + +void RegisterWindow::CreateControls() { + // + CreateWindow("STATIC", "ûע", WS_VISIBLE | WS_CHILD | SS_CENTER, + 10, 20, 360, 30, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ǩ + CreateWindow("STATIC", ":", WS_VISIBLE | WS_CHILD, + 50, 70, 50, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hEmail = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER, + 100, 70, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ȡ֤밴ť + CreateWindow("BUTTON", "ȡ֤", WS_VISIBLE | WS_CHILD, + 100, 110, 200, 30, hwnd, (HMENU)1, GetModuleHandle(NULL), NULL); + + // ֤ǩ + CreateWindow("STATIC", "֤:", WS_VISIBLE | WS_CHILD, + 50, 160, 50, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hCode = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER, + 100, 160, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ǩ + CreateWindow("STATIC", ":", WS_VISIBLE | WS_CHILD, + 50, 200, 50, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hPassword = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_PASSWORD, + 100, 200, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // ȷǩ + CreateWindow("STATIC", "ȷ:", WS_VISIBLE | WS_CHILD, + 30, 230, 70, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hConfirmPassword = CreateWindow("EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_PASSWORD, + 100, 230, 200, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // Ҫʾ + CreateWindow("STATIC", "Ҫ: 6-10λСдĸ", + WS_VISIBLE | WS_CHILD | SS_CENTER, + 50, 260, 300, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // עᰴť + CreateWindow("BUTTON", "ע", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 100, 300, 80, 30, hwnd, (HMENU)2, GetModuleHandle(NULL), NULL); + + // ذť + CreateWindow("BUTTON", "", WS_VISIBLE | WS_CHILD, + 200, 300, 80, 30, hwnd, (HMENU)3, GetModuleHandle(NULL), NULL); + + // Ϣǩ + hMessage = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_CENTER, + 50, 340, 300, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); +} + +LRESULT CALLBACK RegisterWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_COMMAND: { + int cmd = LOWORD(wParam); + if (cmd == 1) { // ȡ֤ + OnGetCode(); + } else if (cmd == 2) { // עᰴť + OnRegister(); + } else if (cmd == 3) { // ذť + OnBack(); + } + break; + } + case WM_CLOSE: + DestroyWindow(hwnd); + LoginWindow::Show(); + break; + case WM_DESTROY: + // WM_DESTROYеPostQuitMessage + break; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +void RegisterWindow::OnGetCode() { + char email[100]; + GetWindowText(hEmail, email, sizeof(email)); + + std::string strEmail(email); + + if (strEmail.empty()) { + SetWindowText(hMessage, "ַ"); + return; + } + + UserManager& userManager = UserManager::getInstance(); + if (!userManager.validateEmailFormat(strEmail)) { + SetWindowText(hMessage, "ʽȷ"); + return; + } + + if (userManager.isEmailRegistered(strEmail)) { + SetWindowText(hMessage, "ע"); + return; + } + + // ʾʾ + SetWindowText(hMessage, "ڷ֤룬Ժ..."); + + // ɲ֤루ʾڽϣ + generatedCode = userManager.generateRegistrationCode(strEmail); + + if (!generatedCode.empty()) { + SetWindowText(hMessage, "֤ѷ͵䣬գ"); + // ֤ûֶ + SetWindowText(hCode, ""); + // ý㵽֤ + SetFocus(hCode); + } else { + SetWindowText(hMessage, "ʼʧܣַ"); + generatedCode = ""; // ֤ + } +} + +void RegisterWindow::OnRegister() { + char email[100], code[100], password[100], confirmPassword[100]; + GetWindowText(hEmail, email, sizeof(email)); + GetWindowText(hCode, code, sizeof(code)); + GetWindowText(hPassword, password, sizeof(password)); + GetWindowText(hConfirmPassword, confirmPassword, sizeof(confirmPassword)); + + std::string strEmail(email); + std::string strCode(code); + std::string strPassword(password); + std::string strConfirmPassword(confirmPassword); + + // ֤ + if (strEmail.empty() || strCode.empty() || strPassword.empty() || strConfirmPassword.empty()) { + SetWindowText(hMessage, "дֶ"); + return; + } + + // ֤֤ + if (strCode != generatedCode) { + SetWindowText(hMessage, "֤벻ȷ"); + return; + } + + // ֤һ + if (strPassword != strConfirmPassword) { + SetWindowText(hMessage, "벻һ"); + return; + } + + UserManager& userManager = UserManager::getInstance(); + + // ֤ʽ + if (!userManager.validatePasswordFormat(strPassword)) { + SetWindowText(hMessage, "ʽҪ"); + return; + } + + // עû + if (registerUserWithPassword(strEmail, strPassword)) { + SetWindowText(hMessage, "עɹת¼ҳ..."); + Sleep(2000); // ȴ2ʾɹϢ + OnBack(); + } else { + SetWindowText(hMessage, "עʧܣ"); + } +} + +bool RegisterWindow::registerUserWithPassword(const std::string& email, const std::string& password) { + UserManager& userManager = UserManager::getInstance(); + return userManager.registerUserWithPassword(email, password); +} + +void RegisterWindow::OnBack() { + DestroyWindow(hwnd); + hwnd = NULL; // ôھ + LoginWindow::Show(); +} diff --git a/src/RegisterWindow.h b/src/RegisterWindow.h new file mode 100644 index 0000000..72d53eb --- /dev/null +++ b/src/RegisterWindow.h @@ -0,0 +1,30 @@ +#ifndef REGISTERWINDOW_H +#define REGISTERWINDOW_H + +#include +#include + +class RegisterWindow { +public: + static void Show(); + static HWND GetHandle() { return hwnd; } + +private: + static HWND hwnd; + static HWND hEmail; + static HWND hCode; + static HWND hPassword; + static HWND hConfirmPassword; + static HWND hMessage; + + static std::string generatedCode; + + static void CreateControls(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static void OnGetCode(); + static void OnRegister(); + static void OnBack(); + static bool registerUserWithPassword(const std::string& email, const std::string& password); +}; + +#endif diff --git a/src/RegisterWindow.o b/src/RegisterWindow.o new file mode 100644 index 0000000..9ff9c5d Binary files /dev/null and b/src/RegisterWindow.o differ diff --git a/src/SelectionWindow.cpp b/src/SelectionWindow.cpp new file mode 100644 index 0000000..3ac56b0 --- /dev/null +++ b/src/SelectionWindow.cpp @@ -0,0 +1,161 @@ +#include "SelectionWindow.h" +#include "QuestionWindow.h" +#include "LoginWindow.h" +#include "UserManager.h" +#include + +HWND SelectionWindow::hwnd = NULL; +HWND SelectionWindow::hQuestionCount = NULL; + +void SelectionWindow::Show() { + // Ѵڣ + if (hwnd != NULL) { + DestroyWindow(hwnd); + hwnd = NULL; + } + + WNDCLASSEX wc; + memset(&wc, 0, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszClassName = "SelectionWindow"; + + RegisterClassEx(&wc); + + hwnd = CreateWindowEx(0, "SelectionWindow", "ѧѧϰ - ѡѶ", + WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 400, 350, + NULL, NULL, GetModuleHandle(NULL), NULL); + + if (!hwnd) { + MessageBox(NULL, "ѡ񴰿ʧ", "", MB_OK | MB_ICONERROR); + return; + } + + CreateControls(); + + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); +} + +void SelectionWindow::CreateControls() { + // + CreateWindow("STATIC", "ѡĿѶ", WS_VISIBLE | WS_CHILD | SS_CENTER, + 10, 20, 360, 30, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // Ŀ + CreateWindow("STATIC", "Ŀ (10-30):", WS_VISIBLE | WS_CHILD, + 50, 60, 120, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + hQuestionCount = CreateWindow("EDIT", "10", WS_VISIBLE | WS_CHILD | WS_BORDER, + 180, 60, 60, 25, hwnd, NULL, GetModuleHandle(NULL), NULL); + + // Сѧť + CreateWindow("BUTTON", "СѧĿ", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 100, 100, 200, 40, hwnd, (HMENU)1, GetModuleHandle(NULL), NULL); + + // аť + CreateWindow("BUTTON", "Ŀ", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 100, 150, 200, 40, hwnd, (HMENU)2, GetModuleHandle(NULL), NULL); + + // аť + CreateWindow("BUTTON", "Ŀ", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 100, 200, 200, 40, hwnd, (HMENU)3, GetModuleHandle(NULL), NULL); + + // ˳¼ť + CreateWindow("BUTTON", "˳¼", WS_VISIBLE | WS_CHILD, + 150, 260, 100, 30, hwnd, (HMENU)4, GetModuleHandle(NULL), NULL); +} + +LRESULT CALLBACK SelectionWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_COMMAND: { + int cmd = LOWORD(wParam); + if (cmd == 1) { // СѧĿ + OnElementarySelected(); + } else if (cmd == 2) { // Ŀ + OnMiddleSchoolSelected(); + } else if (cmd == 3) { // Ŀ + OnHighSchoolSelected(); + } else if (cmd == 4) { // ˳¼ + OnLogout(); + } + break; + } + case WM_CLOSE: + DestroyWindow(hwnd); + LoginWindow::Show(); // رѡ񴰿ʱص¼ + break; + case WM_DESTROY: + // WM_DESTROYеPostQuitMessage + break; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +bool SelectionWindow::validateQuestionCount() { + int count = getQuestionCount(); + if (count < 10 || count > 30) { + MessageBox(hwnd, "Ŀ10-30֮", "", MB_OK | MB_ICONWARNING); + SetFocus(hQuestionCount); + return false; + } + return true; +} + +int SelectionWindow::getQuestionCount() { + char countText[10]; + GetWindowText(hQuestionCount, countText, sizeof(countText)); + + // תΪ + int count = atoi(countText); + if (count <= 0) { + count = 10; // Ĭֵ + } + return count; +} + +void SelectionWindow::OnElementarySelected() { + if (!validateQuestionCount()) { + return; + } + + int questionCount = getQuestionCount(); + DestroyWindow(hwnd); + hwnd = NULL; + QuestionWindow::Show("elementary", questionCount); +} + +void SelectionWindow::OnMiddleSchoolSelected() { + if (!validateQuestionCount()) { + return; + } + + int questionCount = getQuestionCount(); + DestroyWindow(hwnd); + hwnd = NULL; + QuestionWindow::Show("middle", questionCount); +} + +void SelectionWindow::OnHighSchoolSelected() { + if (!validateQuestionCount()) { + return; + } + + int questionCount = getQuestionCount(); + DestroyWindow(hwnd); + hwnd = NULL; + QuestionWindow::Show("high", questionCount); +} + +void SelectionWindow::OnLogout() { + UserManager::getInstance().logout(); + DestroyWindow(hwnd); + hwnd = NULL; + LoginWindow::Show(); +} diff --git a/src/SelectionWindow.h b/src/SelectionWindow.h new file mode 100644 index 0000000..6db2023 --- /dev/null +++ b/src/SelectionWindow.h @@ -0,0 +1,25 @@ +#ifndef SELECTIONWINDOW_H +#define SELECTIONWINDOW_H + +#include + +class SelectionWindow { +public: + static void Show(); + static HWND GetHandle() { return hwnd; } + +private: + static HWND hwnd; + static HWND hQuestionCount; + + static void CreateControls(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static void OnElementarySelected(); + static void OnMiddleSchoolSelected(); + static void OnHighSchoolSelected(); + static void OnLogout(); + static bool validateQuestionCount(); + static int getQuestionCount(); +}; + +#endif diff --git a/src/SelectionWindow.o b/src/SelectionWindow.o new file mode 100644 index 0000000..0da6ed0 Binary files /dev/null and b/src/SelectionWindow.o differ diff --git a/src/User.cpp b/src/User.cpp new file mode 100644 index 0000000..7600855 --- /dev/null +++ b/src/User.cpp @@ -0,0 +1,24 @@ +#include "User.h" + +User::User(const std::string& email, const std::string& password, const std::string& userType) + : email(email), password(password), userType(userType) {} + +std::string User::getEmail() const { + return email; +} + +std::string User::getPassword() const { + return password; +} + +std::string User::getUserType() const { + return userType; +} + +void User::setPassword(const std::string& newPassword) { + password = newPassword; +} + +bool User::validatePassword(const std::string& password) const { + return this->password == password; +} diff --git a/src/User.h b/src/User.h new file mode 100644 index 0000000..61c60f8 --- /dev/null +++ b/src/User.h @@ -0,0 +1,23 @@ +#ifndef USER_H +#define USER_H + +#include + +class User { +public: + User(const std::string& email, const std::string& password, const std::string& userType); + + std::string getEmail() const; + std::string getPassword() const; + std::string getUserType() const; + void setPassword(const std::string& newPassword); + + bool validatePassword(const std::string& password) const; + +private: + std::string email; + std::string password; + std::string userType; +}; + +#endif diff --git a/src/User.o b/src/User.o new file mode 100644 index 0000000..5ef308f Binary files /dev/null and b/src/User.o differ diff --git a/src/UserManager.cpp b/src/UserManager.cpp new file mode 100644 index 0000000..5da1610 --- /dev/null +++ b/src/UserManager.cpp @@ -0,0 +1,164 @@ +#include "UserManager.h" +#include "User.h" +#include "EmailSender.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +UserManager::UserManager() { + currentUser = NULL; + srand(static_cast(time(NULL))); + loadUsers(); +} + +UserManager& UserManager::getInstance() { + static UserManager instance; + return instance; +} + +bool UserManager::validateEmailFormat(const std::string& email) { + size_t atPos = email.find('@'); + size_t dotPos = email.find('.'); + return atPos != std::string::npos && dotPos != std::string::npos && atPos < dotPos; +} + +bool UserManager::validatePasswordFormat(const std::string& password) { + if (password.length() < 6 || password.length() > 10) return false; + + bool hasUpper = false, hasLower = false, hasDigit = false; + for (size_t i = 0; i < password.length(); ++i) { + char c = password[i]; + if (isupper(c)) hasUpper = true; + if (islower(c)) hasLower = true; + if (isdigit(c)) hasDigit = true; + } + + return hasUpper && hasLower && hasDigit; +} + +std::string UserManager::generateRandomCode(int length) { + const std::string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + std::string code; + + for (int i = 0; i < length; ++i) { + code += chars[rand() % chars.size()]; + } + return code; +} + +bool UserManager::sendEmail(const std::string& email, const std::string& code) { + // ʹEmailSender෢ʼ + return EmailSender::sendVerificationCode(email, code); +} + +std::string UserManager::generateRegistrationCode(const std::string& email) { + std::string code = generateRandomCode(6); // 6λ֤ + + // ʼ + if (sendEmail(email, code)) { + return code; + } else { + return ""; // ʧܷؿַ + } +} + +bool UserManager::registerUser(const std::string& email) { + if (isEmailRegistered(email)) return false; + + std::string defaultPassword = "Temp123"; + users.push_back(User(email, defaultPassword, "elementary")); + saveUsers(); + return true; +} + +bool UserManager::registerUserWithPassword(const std::string& email, const std::string& password) { + if (isEmailRegistered(email)) return false; + + // ֤ʽ + if (!validatePasswordFormat(password)) { + return false; + } + + users.push_back(User(email, password, "elementary")); + saveUsers(); + return true; +} + +bool UserManager::login(const std::string& email, const std::string& password) { + for (size_t i = 0; i < users.size(); ++i) { + User& user = users[i]; + if (user.getEmail() == email && user.validatePassword(password)) { + currentUser = &user; + return true; + } + } + return false; +} + +bool UserManager::changePassword(const std::string& email, const std::string& oldPassword, const std::string& newPassword) { + for (size_t i = 0; i < users.size(); ++i) { + User& user = users[i]; + if (user.getEmail() == email && user.validatePassword(oldPassword)) { + if (validatePasswordFormat(newPassword)) { + user.setPassword(newPassword); + saveUsers(); + return true; + } + } + } + return false; +} + +bool UserManager::isEmailRegistered(const std::string& email) { + for (size_t i = 0; i < users.size(); ++i) { + const User& user = users[i]; + if (user.getEmail() == email) { + return true; + } + } + return false; +} + +void UserManager::loadUsers() { + std::ifstream file("data/users.txt"); + if (!file) return; + + std::string line; + while (std::getline(file, line)) { + size_t pos1 = line.find(','); + size_t pos2 = line.find(',', pos1 + 1); + + if (pos1 != std::string::npos && pos2 != std::string::npos) { + std::string email = line.substr(0, pos1); + std::string password = line.substr(pos1 + 1, pos2 - pos1 - 1); + std::string userType = line.substr(pos2 + 1); + + users.push_back(User(email, password, userType)); + } + } +} + +void UserManager::saveUsers() { + // Ŀ¼ + CreateDirectory("data", NULL); + + std::ofstream file("data/users.txt"); + for (size_t i = 0; i < users.size(); ++i) { + const User& user = users[i]; + file << user.getEmail() << "," << user.getPassword() << "," << user.getUserType() << "\n"; + } +} + +User* UserManager::getCurrentUser() { + return currentUser; +} + +void UserManager::logout() { + currentUser = NULL; +} diff --git a/src/UserManager.h b/src/UserManager.h new file mode 100644 index 0000000..407167f --- /dev/null +++ b/src/UserManager.h @@ -0,0 +1,36 @@ +#ifndef USERMANAGER_H +#define USERMANAGER_H + +#include "User.h" +#include +#include + +class UserManager { +public: + static UserManager& getInstance(); + + bool registerUser(const std::string& email); + bool registerUserWithPassword(const std::string& email, const std::string& password); + bool login(const std::string& email, const std::string& password); + bool changePassword(const std::string& email, const std::string& oldPassword, const std::string& newPassword); + User* getCurrentUser(); + void logout(); + + // ޸ķǩemail + std::string generateRegistrationCode(const std::string& email); + std::string generateRandomCode(int length); + bool isEmailRegistered(const std::string& email); + bool validatePasswordFormat(const std::string& password); + bool validateEmailFormat(const std::string& email); + + void loadUsers(); + void saveUsers(); + +private: + UserManager(); + std::vector users; + User* currentUser; + bool sendEmail(const std::string& email, const std::string& code); +}; + +#endif diff --git a/src/UserManager.o b/src/UserManager.o new file mode 100644 index 0000000..9c59479 Binary files /dev/null and b/src/UserManager.o differ diff --git a/src/data/users.txt b/src/data/users.txt new file mode 100644 index 0000000..d6395d3 --- /dev/null +++ b/src/data/users.txt @@ -0,0 +1,2 @@ +1853439381@qq.com,Temp123,elementary +2470975401@qq.com,123456QWe,elementary diff --git a/src/email_send.log b/src/email_send.log new file mode 100644 index 0000000..a277b77 --- /dev/null +++ b/src/email_send.log @@ -0,0 +1,3 @@ +? ɹ֤뵽: 3675658020@qq.com | ֤: OP9R0N | ʱ: 22:45:10 +? ɹ֤뵽: 3675658020@qq.com | ֤: B3XMEI | ʱ: 22:45:10 +? ɹ֤뵽: 3675658020@qq.com | ֤: BG5ZSN | ʱ: 22:45:10 diff --git a/src/email_send_log.txt b/src/email_send_log.txt new file mode 100644 index 0000000..11ac2ea --- /dev/null +++ b/src/email_send_log.txt @@ -0,0 +1,13 @@ +=== ʼͼ¼ === +ʱ: Oct 7 2025 23:35:05 +: PowerShell +: 3675658020@qq.com +ռ: 2470975401@qq.com +֤: ZH4RXI +ִн: ڷʼ: 2470975401@qq.com +֤: ZH4RXI +ʼͳɹ +SUCCESS + +========================= + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..91ac453 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include "LoginWindow.h" + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + // ʼ + srand(static_cast(time(NULL))); + + // ʾ¼ + LoginWindow::Show(); + + // Ϣѭ + MSG msg; + BOOL bRet; + while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { + if (bRet == -1) { + // + break; + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return msg.wParam; +} diff --git a/src/main.o b/src/main.o new file mode 100644 index 0000000..65500ab Binary files /dev/null and b/src/main.o differ diff --git a/src/send_email.ps1 b/src/send_email.ps1 new file mode 100644 index 0000000..165ed6a --- /dev/null +++ b/src/send_email.ps1 @@ -0,0 +1,44 @@ +# ѧѧϰʼͽű +# +$SMTPServer = "smtp.qq.com" +$SMTPPort = "587" +$Username = "3675658020@qq.com" +$Password = "lsagdbxwfolhcheb" +$EmailFrom = "3675658020@qq.com" +$EmailTo = "2470975401@qq.com" +$Subject = "ѧѧϰ - ע֤" +$Body = @" +ӭעѧѧϰ + +ע֤ǣZH4RXI + +֤ЧΪ10ӣ뾡ʹá + +û֤룬Դʼ + +лл +ѧѧϰŶ +"@ + +Write-Host "ڷʼ: $EmailTo" +Write-Host "֤: ZH4RXI" + +try { + # ʼϢ + $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom, $EmailTo, $Subject, $Body) + + # SMTPͻ + $SMTPClient = New-Object Net.Mail.SmtpClient($SMTPServer, $SMTPPort) + $SMTPClient.EnableSsl = $true + $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password) + + # ʼ + $SMTPClient.Send($SMTPMessage) + + Write-Host "ʼͳɹ" -ForegroundColor Green + Write-Output "SUCCESS" + +} catch { + Write-Host "ʼʧ: $($_.Exception.Message)" -ForegroundColor Red + Write-Output "ERROR: $($_.Exception.Message)" +} \ No newline at end of file diff --git a/src/test3.dev b/src/test3.dev new file mode 100644 index 0000000..58a47d1 --- /dev/null +++ b/src/test3.dev @@ -0,0 +1,242 @@ +[Project] +FileName=test3.dev +Name=Ŀ1 +Type=0 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=-lws2_32 -lwininet_@@_ +IsCpp=1 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName=test3.exe +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000000 +UnitCount=19 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=1.0.0.0 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit9] +FileName=User.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit1] +FileName=Question.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=UserManager.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=UserManager.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=User.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=QuestionGenerator.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=QuestionGenerator.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=Question.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=LoginWindow.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=LoginWindow.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=RegisterWindow.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=RegisterWindow.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=QuestionWindow.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=QuestionWindow.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=main.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=EmailSender.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=EmailSender.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=SelectionWindow.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=SelectionWindow.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/src/test3.exe b/src/test3.exe new file mode 100644 index 0000000..28b2834 Binary files /dev/null and b/src/test3.exe differ diff --git a/src/test3.layout b/src/test3.layout new file mode 100644 index 0000000..5e06b86 --- /dev/null +++ b/src/test3.layout @@ -0,0 +1,98 @@ +[Editor_0] +CursorCol=7 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editors] +Order=8,0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18 +Focused=13 +[Editor_1] +CursorCol=7 +CursorRow=36 +TopLine=1 +LeftChar=1 +[Editor_2] +CursorCol=2 +CursorRow=164 +TopLine=122 +LeftChar=1 +[Editor_3] +CursorCol=2 +CursorRow=24 +TopLine=1 +LeftChar=1 +[Editor_4] +CursorCol=7 +CursorRow=29 +TopLine=1 +LeftChar=1 +[Editor_5] +CursorCol=2 +CursorRow=364 +TopLine=326 +LeftChar=1 +[Editor_6] +CursorCol=2 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_7] +CursorCol=7 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_8] +CursorCol=7 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_9] +CursorCol=2 +CursorRow=135 +TopLine=1 +LeftChar=1 +[Editor_10] +CursorCol=7 +CursorRow=30 +TopLine=1 +LeftChar=1 +[Editor_11] +CursorCol=2 +CursorRow=225 +TopLine=131 +LeftChar=1 +[Editor_12] +CursorCol=7 +CursorRow=32 +TopLine=1 +LeftChar=1 +[Editor_13] +CursorCol=18 +CursorRow=179 +TopLine=150 +LeftChar=1 +[Editor_14] +CursorCol=2 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_15] +CursorCol=56 +CursorRow=32 +TopLine=1 +LeftChar=1 +[Editor_16] +CursorCol=7 +CursorRow=16 +TopLine=1 +LeftChar=1 +[Editor_17] +CursorCol=2 +CursorRow=161 +TopLine=1 +LeftChar=1 +[Editor_18] +CursorCol=7 +CursorRow=25 +TopLine=1 +LeftChar=1