diff --git a/doc/README.md b/doc/README.md index 6fa1bee..aacf4a3 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,206 +1,2 @@ # Pair-Programming -## **项目概述** - -数学学习系统是一个面向小初高学生的数学学习软件,旨在通过生成针对性的数学题目帮助学生进行练习和巩固数学知识。该系统采用前后端分离架构,前端基于 Electron 构建桌面应用,后端使用 Java 提供 API 服务。 - -## **项目结构** - -pair-programming/ - -├── src/ - -│ ├── electron-frontend/ # Electron前端 - -│ │ ├── resources/ - -│ │ │ ├── renderer/ # 渲染进程页面 - -│ │ │ │ ├── main.html # 主页面 - -│ │ │ │ ├── login.html # 登录页面 - -│ │ │ │ └── result.html # 结果页面 - -│ │ │ │ └── quiz.html # 答题页面 - -│ │ │ │ └── register.html # 注册页面 - -│ │ │ ├── main.js # 主进程代码 - -│ │ │ └── preload.js # 预加载脚本 - -│ │ ├── package.json # 前端依赖配置 - -│ │ └── package-lock.json # 依赖版本锁定文件 - -│ └── java-backend/ # Java后端 - -│ └── math\_learn/ # 数学学习系统后端代码 - -│ ├── .idea/ # IntelliJ IDEA配置 - -│ ├── src/ # 源代码 - -│ │ └── com/mathlearn/ - -│ │ ├── Main.java # 主程序入口 - -│ │ ├── generator/ # 题目生成业务 - -│ │ │ ├── QuestionGenerator # 题目生成器接口 - -│ │ │ └── SeniorHighGenerator.java # 高中题目生成器 - -│ │ └──model/ # 实体类 - -│ │ ├── api/ # API响应类 - -│ │ ├── exam/ # 题目试卷类 - -│ │ └── user/ # 用户类 - -│ └── .gitignore # Git忽略文件 - -└──doc/ #说明文档 - - └── README.md - -## **功能说明** - -**核心功能** - -1.用户认证:支持用户注册、登录、退出、修改密码功能 - -2.题目生成:根据用户选择的学段(小学、初中、高中)生成相应难度的数学题目 - -3.答题系统:提供交互式答题界面 - -4.成绩评估:答题完成后计算并展示得分和评价 - - - -## **题目生成** - -系统根据不同学段生成相应难度的题目: - -高中阶段包含对数等高级数学题目 - -题目数量可在 10-30 之间选择 - -生成过程包含详细日志记录,便于调试和跟踪 - - - -## **技术栈** - -前端技术 - -Electron:用于构建跨平台桌面应用 - -HTML/CSS:页面结构和样式 - -JavaScript:交互逻辑 - -node-fetch:网络请求 - -后端技术 - -Java:后端服务开发 - -JDK 21:Java 开发环境 - - - -## **环境配置与运行** - -后端运行: - -1.确保安装 JDK 21 - -2.在 IDE(如 IntelliJ IDEA)中打开math\_learn项目 - -3.运行com.mathlearn.Main主类启动后端服务 - - - -## **API 接口说明** - -生成试卷 - -端点:/generate-exam - -方法:POST - -参数: - -  sessionId:用户会话 ID - -  userType:用户类型(小学 / 初中 / 高中) - -  questionCount:题目数量(10-30) - -返回:包含试卷信息和第一题的 JSON 响应 - - - -## **退出登录** - -端点:/logout - -方法:POST - -参数: - -sessionId:用户会话 ID - -返回:退出结果 - - - -## **注意事项** - -确保后端服务在本地 8080 端口运行,否则前端无法正常获取数据 - -题目生成可能需要一定时间,系统设置了 15 秒超时控制 - -若遇到连接问题,请检查: - -1.后端 Java 程序是否运行 - -2.网络连接是否正常 - -3.端口 8080 是否被占用 - - - -## **使用教程** - -1.后端启动 - -两种路径: - - 1)安装mathlearn\_setup.exe安装包,根据指示完成下载 - - 确保端口8080未被占用 - - backend目录有jar和exe两种方式启动后端服务器 - - 2)在 IDE(如 IntelliJ IDEA,或其他编程软件)中打开math\_learn项目 - - 确保端口8080未被占用 - - 运行com.mathlearn.Main主类启动后端服务 - -2.前端运行: - -安装mathlearn\_setup.exe安装包,根据指示完成下载 - -3.根据邮箱注册自己的账号并完成登录 - -4\.根据用户类型选择不同的题目类型,并输入所需题目数量(10-30题) - -5\.完成答题并查看所得分数 - -6\.安装目录下backend/math_questions文件夹里存储用户答题数据 - diff --git a/src/electron-frontend/package.json b/src/electron-frontend/package.json index 8a20168..85b1de1 100644 --- a/src/electron-frontend/package.json +++ b/src/electron-frontend/package.json @@ -2,16 +2,15 @@ "name": "math-learning-app", "version": "1.0.0", "description": "小初高数学学习软件", - "main": "resources/main.js", + "main": "src/main.js", "scripts": { "start": "electron .", "dev": "electron . --dev", - "build": "electron-builder", - "dist": "electron-builder --publish=never" + "build": "electron-builder" }, "devDependencies": { - "electron": "^22.3.27", - "electron-builder": "^24.13.3" + "electron": "^22.0.0", + "electron-builder": "^24.0.0" }, "build": { "appId": "com.mathlearning.app", @@ -20,33 +19,16 @@ "output": "dist" }, "files": [ - "resources/**/*", - "!resources/node_modules", - "!**/*.map", - "!**/*.log" + "src/**/*", + "styles/**/*", + "assets/**/*" ], "win": { - "target": [ - { - "target": "nsis", - "arch": [ - "x64" - ] - } - ], - "icon": "resources/icon.ico" - }, - "nsis": { - "oneClick": false, - "allowToChangeInstallationDirectory": true, - "createDesktopShortcut": true, - "createStartMenuShortcut": true, - "shortcutName": "数学学习系统" - }, - "compression": "maximum", - "asar": true + "target": "nsis", + "icon": "assets/icon.ico" + } }, "dependencies": { "node-fetch": "^2.7.0" } -} \ No newline at end of file +} diff --git a/src/electron-frontend/resources/main.js b/src/electron-frontend/resources/main.js index 80668d2..688dacc 100644 --- a/src/electron-frontend/resources/main.js +++ b/src/electron-frontend/resources/main.js @@ -4,43 +4,24 @@ const path = require('path'); let mainWindow; -function createWindow(initialPage = 'login') { - // 如果已存在窗口,先关闭 - if (mainWindow) { - mainWindow.close(); - mainWindow = null; - } - +function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, - preload: path.join(__dirname, 'preload.js'), - webSecurity: false, - backgroundThrottling: false + preload: path.join(__dirname, 'preload.js'), // 确保路径正确 + webSecurity: false // 开发时可以关闭,避免CORS问题 }, - show: false, - backgroundColor: '#ffffff' + icon: path.join(__dirname, 'assets/icon.png') // 可选 }); - // 在窗口准备好后显示 - mainWindow.once('ready-to-show', () => { - mainWindow.show(); - mainWindow.focus(); - }); + // 加载登录页面 + mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); - // 根据参数加载不同页面 - if (initialPage === 'login') { - mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); - } else { - mainWindow.loadFile(path.join(__dirname, `renderer/${initialPage}.html`)); - } - + // 开发时打开开发者工具 mainWindow.webContents.openDevTools(); - - return mainWindow; } function createMenu() { @@ -99,22 +80,12 @@ ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = } }); -// 修改导航处理 - 对于登录页面完全重新创建窗口 +// 页面导航 ipcMain.handle('navigate-to', (event, page) => { - if (page === 'login') { - // 对于登录页面,完全重新创建窗口 - createWindow('login'); - } else { - // 其他页面使用普通导航 - mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); - } + mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); }); -// 修复:只有一个 app.whenReady() 调用 -app.whenReady().then(() => { - createWindow('login'); - createMenu(); // 在这里创建菜单 -}); +app.whenReady().then(createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { @@ -124,6 +95,6 @@ app.on('window-all-closed', () => { app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { - createWindow('login'); + createWindow(); } }); \ No newline at end of file diff --git a/src/electron-frontend/resources/preload.js b/src/electron-frontend/resources/preload.js index dd844a6..5f08f7e 100644 --- a/src/electron-frontend/resources/preload.js +++ b/src/electron-frontend/resources/preload.js @@ -1,8 +1,60 @@ const { contextBridge, ipcRenderer } = require('electron'); +// 统一的会话管理器 +const SessionManager = { + // 获取当前用户会话(强制从存储读取) + getCurrentUser() { + try { + const session = localStorage.getItem('userSession'); + return session ? JSON.parse(session) : null; + } catch (error) { + console.error('获取用户会话失败:', error); + return null; + } + }, + + // 获取当前考试会话 + getCurrentExam() { + try { + const exam = localStorage.getItem('currentExam'); + return exam ? JSON.parse(exam) : null; + } catch (error) { + console.error('获取考试会话失败:', error); + return null; + } + }, + + // 清除所有会话 + clearAllSessions() { + localStorage.removeItem('userSession'); + localStorage.removeItem('currentExam'); + localStorage.removeItem('examResult'); + console.log('所有会话已清除'); + }, + + // 验证会话是否有效 + validateUserSession() { + const user = this.getCurrentUser(); + if (!user || !user.sessionId) { + return false; + } + + // 可以添加更多验证逻辑,比如检查过期时间等 + return true; + }, + + // 刷新用户会话(在修改密码等操作后) + refreshUserSession(updatedUserData) { + if (updatedUserData) { + localStorage.setItem('userSession', JSON.stringify(updatedUserData)); + } + } + +}; + // 暴露安全的API给渲染进程 contextBridge.exposeInMainWorld('electronAPI', { - // 简单的导航功能 + // 页面导航 navigateTo: (page) => ipcRenderer.invoke('navigate-to', page), // 存储会话数据 @@ -17,13 +69,34 @@ contextBridge.exposeInMainWorld('electronAPI', { removeSession: (key) => { localStorage.removeItem(key); + }, + + // 新增:获取当前会话状态 + getSessionState: () => { + return SessionManager.validateSession(); + }, + + // 新增:强制清除所有会话 + clearAllSessions: () => { + SessionManager.clearAllSessions(); + }, + // 新增会话验证方法 + validateSession: () => { + return SessionManager.validateUserSession(); + }, + + // 新增会话刷新方法 + refreshSession: (userData) => { + SessionManager.refreshUserSession(userData); } }); -// API 请求 +// 直接在渲染进程中暴露 API 调用函数 contextBridge.exposeInMainWorld('api', { request: async (endpoint, method = 'POST', data = {}) => { try { + console.log('API Request:', endpoint, method, data); + const url = `http://localhost:8080/api${endpoint}`; const formData = new URLSearchParams(); @@ -40,8 +113,10 @@ contextBridge.exposeInMainWorld('api', { }); const result = await response.json(); + console.log('API Response:', result); return result; } catch (error) { + console.error('API Error:', error); return { success: false, message: `网络错误: ${error.message}`, @@ -49,4 +124,6 @@ contextBridge.exposeInMainWorld('api', { }; } } -}); \ No newline at end of file +}); + +console.log('Preload script loaded successfully'); \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/login.html b/src/electron-frontend/resources/renderer/login.html index 60fa060..7d51f60 100644 --- a/src/electron-frontend/resources/renderer/login.html +++ b/src/electron-frontend/resources/renderer/login.html @@ -27,12 +27,6 @@ font-size: 16px; } - input:focus { - border-color: #007acc; - outline: none; - box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2); - } - button { width: 100%; padding: 12px; @@ -63,10 +57,10 @@

数学试卷自动生成系统

- +
- +
@@ -75,18 +69,24 @@ diff --git a/src/electron-frontend/resources/renderer/register.html b/src/electron-frontend/resources/renderer/register.html index a26163b..dbffcca 100644 --- a/src/electron-frontend/resources/renderer/register.html +++ b/src/electron-frontend/resources/renderer/register.html @@ -147,7 +147,7 @@ getCodeBtn.textContent = '发送中...'; // 调用后端API获取验证码 - 使用正确的路径 - const result = await window.api.request('/send-registration-code', 'POST', { + const result = await window.api.request('/api/send-registration-code', 'POST', { email: email }); @@ -197,7 +197,7 @@ } try { - const result = await window.api.request('/register', 'POST', { + const result = await window.api.request('/api/register', 'POST', { email, registrationCode, username, password, confirmPassword, userType }); diff --git a/src/electron-frontend/resources/style/common.css b/src/electron-frontend/resources/style/common.css index 3291f4c..19382d9 100644 --- a/src/electron-frontend/resources/style/common.css +++ b/src/electron-frontend/resources/style/common.css @@ -36,66 +36,83 @@ body { border: 1px solid #bee5eb; } -/* 专门修复输入框渲染问题 */ -input[type="text"], -input[type="password"], -input[type="number"] { - -webkit-appearance: none !important; - appearance: none !important; - border: 1px solid #ddd !important; - background-color: white !important; - box-shadow: none !important; - outline: none !important; - transform: translateZ(0); - backface-visibility: hidden; - perspective: 1000; -} - -/* 强制焦点状态 */ -input:focus { - border-color: #007acc !important; - box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2) !important; - outline: none !important; -} - -/* 修复可能的透明问题 */ -input:not([disabled]):not([readonly]) { - opacity: 1 !important; - visibility: visible !important; -} - -/* 强制重绘的动画 */ -@keyframes forceRepaint { - 0% { - opacity: 0.999; - } - - 100% { - opacity: 1; - } -} - -.force-repaint { - animation: forceRepaint 0.001s; -} - -/* 专门为模态框输入框添加样式 */ -#passwordModal input[type="password"] { - -webkit-appearance: none !important; - appearance: none !important; - border: 1px solid #ddd !important; - background-color: white !important; - box-shadow: none !important; - outline: none !important; - transform: translateZ(0); - backface-visibility: hidden; - perspective: 1000; - opacity: 1 !important; - visibility: visible !important; -} - -#passwordModal input[type="password"]:focus { - border-color: #007acc !important; - box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2) !important; - outline: none !important; +/* 基础按钮样式 */ +.btn { + padding: 10px 20px; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +/* 按钮交互效果 */ +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.btn:active { + transform: translateY(0); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); +} + +/* 主按钮 - 用于主要操作 */ +.btn-primary { + background: #007acc; + color: white; +} + +.btn-primary:hover { + background: #005fa3; +} + +/* 次要按钮 - 用于辅助操作 */ +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #5a6268; +} + +/* 成功按钮 - 用于提交、确认等操作 */ +.btn-success { + background: #28a745; + color: white; +} + +.btn-success:hover { + background: #218838; +} + +/* 危险按钮 - 用于删除、退出等操作 */ +.btn-danger { + background: #dc3545; + color: white; +} + +.btn-danger:hover { + background: #c82333; +} + +/* 禁用状态 */ +.btn:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +/* 图标按钮样式(如果需要) */ +.btn-icon-left i { + margin-right: 8px; +} + +.btn-icon-right i { + margin-left: 8px; } \ No newline at end of file diff --git a/src/electron-frontend/resources/style/main.css b/src/electron-frontend/resources/style/main.css deleted file mode 100644 index 35e99e9..0000000 --- a/src/electron-frontend/resources/style/main.css +++ /dev/null @@ -1,389 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -:root { - --primary-color: #4f46e5; - --primary-dark: #4338ca; - --success-color: #10b981; - --warning-color: #f59e0b; - --danger-color: #ef4444; - --info-color: #3b82f6; - --light-bg: #f8fafc; - --dark-text: #1e293b; - --light-text: #64748b; - --border-color: #e2e8f0; - --shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); - --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); -} - -body { - font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - min-height: 100vh; - padding: 20px; - line-height: 1.6; - color: var(--dark-text); -} - -/* 容器样式 */ -.container { - max-width: 1200px; - margin: 0 auto; -} - -/* 卡片样式 */ -.card { - background: white; - border-radius: 16px; - box-shadow: var(--shadow); - backdrop-filter: blur(10px); - border: 1px solid rgba(255, 255, 255, 0.2); -} - -.card-header { - padding: 24px; - border-bottom: 1px solid var(--border-color); -} - -.card-body { - padding: 24px; -} - -/* 按钮样式 */ -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 12px 24px; - border: none; - border-radius: 12px; - font-size: 16px; - font-weight: 600; - cursor: pointer; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - text-decoration: none; - position: relative; - overflow: hidden; -} - -.btn::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); - transition: left 0.5s; -} - -.btn:hover::before { - left: 100%; -} - -.btn-primary { - background: linear-gradient(135deg, var(--primary-color), var(--primary-dark)); - color: white; - box-shadow: 0 4px 14px 0 rgba(79, 70, 229, 0.4); -} - -.btn-primary:hover { - transform: translateY(-2px); - box-shadow: 0 8px 25px 0 rgba(79, 70, 229, 0.5); -} - -.btn-success { - background: linear-gradient(135deg, var(--success-color), #059669); - color: white; - box-shadow: 0 4px 14px 0 rgba(16, 185, 129, 0.4); -} - -.btn-success:hover { - transform: translateY(-2px); - box-shadow: 0 8px 25px 0 rgba(16, 185, 129, 0.5); -} - -.btn-warning { - background: linear-gradient(135deg, var(--warning-color), #d97706); - color: white; - box-shadow: 0 4px 14px 0 rgba(245, 158, 11, 0.4); -} - -.btn-warning:hover { - transform: translateY(-2px); - box-shadow: 0 8px 25px 0 rgba(245, 158, 11, 0.5); -} - -.btn-danger { - background: linear-gradient(135deg, var(--danger-color), #dc2626); - color: white; - box-shadow: 0 4px 14px 0 rgba(239, 68, 68, 0.4); -} - -.btn-danger:hover { - transform: translateY(-2px); - box-shadow: 0 8px 25px 0 rgba(239, 68, 68, 0.5); -} - -.btn-secondary { - background: #64748b; - color: white; -} - -.btn-secondary:hover { - background: #475569; - transform: translateY(-1px); -} - -/* 输入框样式 */ -.form-group { - margin-bottom: 20px; -} - -.form-label { - display: block; - margin-bottom: 8px; - font-weight: 600; - color: var(--dark-text); -} - -.form-control { - width: 100%; - padding: 14px 16px; - border: 2px solid var(--border-color); - border-radius: 12px; - font-size: 16px; - transition: all 0.3s ease; - background: white; - color: var(--dark-text); -} - -.form-control:focus { - outline: none; - border-color: var(--primary-color); - box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); - transform: translateY(-1px); -} - -/* 消息样式 */ -.message { - padding: 16px; - margin-top: 20px; - border-radius: 12px; - text-align: center; - font-weight: 500; - animation: slideIn 0.3s ease-out; -} - -@keyframes slideIn { - from { - opacity: 0; - transform: translateY(-10px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -.message.success { - background: #d1fae5; - color: #065f46; - border: 1px solid #a7f3d0; -} - -.message.error { - background: #fee2e2; - color: #991b1b; - border: 1px solid #fecaca; -} - -.message.info { - background: #dbeafe; - color: #1e40af; - border: 1px solid #bfdbfe; -} - -/* 用户信息卡片 */ -.user-card { - background: linear-gradient(135deg, #f8fafc, #e2e8f0); - padding: 24px; - border-radius: 16px; - border-left: 4px solid var(--primary-color); - margin-bottom: 30px; -} - -.user-card h3 { - margin-bottom: 8px; - color: var(--dark-text); -} - -.user-card p { - color: var(--light-text); - margin-bottom: 4px; -} - -/* 按钮组 */ -.btn-group { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 16px; - margin-bottom: 30px; -} - -/* 模态框样式 */ -.modal-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; - backdrop-filter: blur(4px); - animation: fadeIn 0.3s ease-out; -} - -@keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -.modal-content { - background: white; - padding: 32px; - border-radius: 20px; - box-shadow: var(--shadow-lg); - max-width: 500px; - width: 90%; - animation: scaleIn 0.3s cubic-bezier(0.4, 0, 0.2, 1); -} - -@keyframes scaleIn { - from { - opacity: 0; - transform: scale(0.9); - } - - to { - opacity: 1; - transform: scale(1); - } -} - -/* 标题样式 */ -.page-title { - font-size: 2.5rem; - font-weight: 700; - text-align: center; - margin-bottom: 30px; - background: linear-gradient(135deg, var(--primary-color), #7c3aed); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.section-title { - font-size: 1.5rem; - font-weight: 600; - margin-bottom: 20px; - color: var(--dark-text); -} - -/* 输入框修复 */ -input[type="text"], -input[type="password"], -input[type="number"], -input[type="email"], -select { - -webkit-appearance: none !important; - appearance: none !important; - border: 2px solid var(--border-color) !important; - background-color: white !important; - box-shadow: none !important; - outline: none !important; - transform: translateZ(0); - backface-visibility: hidden; - perspective: 1000; -} - -input:focus, -select:focus { - border-color: var(--primary-color) !important; - box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important; - outline: none !important; -} - -/* 加载动画 */ -.loading { - display: inline-block; - width: 20px; - height: 20px; - border: 3px solid rgba(255, 255, 255, .3); - border-radius: 50%; - border-top-color: #fff; - animation: spin 1s ease-in-out infinite; -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -/* 响应式设计 */ -@media (max-width: 768px) { - body { - padding: 10px; - } - - .btn-group { - grid-template-columns: 1fr; - } - - .page-title { - font-size: 2rem; - } - - .modal-content { - padding: 24px; - margin: 20px; - } -} - -/* 特殊效果 */ -.glass-effect { - background: rgba(255, 255, 255, 0.25); - backdrop-filter: blur(10px); - border: 1px solid rgba(255, 255, 255, 0.18); -} - -.pulse { - animation: pulse 2s infinite; -} - -@keyframes pulse { - 0% { - box-shadow: 0 0 0 0 rgba(79, 70, 229, 0.4); - } - - 70% { - box-shadow: 0 0 0 10px rgba(79, 70, 229, 0); - } - - 100% { - box-shadow: 0 0 0 0 rgba(79, 70, 229, 0); - } -} \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/.name b/src/java-backend/math_learn/.idea/.name deleted file mode 100644 index 002da1d..0000000 --- a/src/java-backend/math_learn/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -Main.java \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml b/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml deleted file mode 100644 index 49743a9..0000000 --- a/src/java-backend/math_learn/.idea/artifacts/math_learning_system_jar.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - $PROJECT_DIR$/../../../../../../electronPro/MATHLEARN/backend - - - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/compiler.xml b/src/java-backend/math_learn/.idea/compiler.xml deleted file mode 100644 index 1f3d83c..0000000 --- a/src/java-backend/math_learn/.idea/compiler.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/encodings.xml b/src/java-backend/math_learn/.idea/encodings.xml deleted file mode 100644 index aa00ffa..0000000 --- a/src/java-backend/math_learn/.idea/encodings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/jarRepositories.xml b/src/java-backend/math_learn/.idea/jarRepositories.xml deleted file mode 100644 index 712ab9d..0000000 --- a/src/java-backend/math_learn/.idea/jarRepositories.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/libraries/Java_EE_6_Java_EE_6.xml b/src/java-backend/math_learn/.idea/libraries/Java_EE_6_Java_EE_6.xml deleted file mode 100644 index bef28b5..0000000 --- a/src/java-backend/math_learn/.idea/libraries/Java_EE_6_Java_EE_6.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/.idea/misc.xml b/src/java-backend/math_learn/.idea/misc.xml index fdc35ea..6f29fee 100644 --- a/src/java-backend/math_learn/.idea/misc.xml +++ b/src/java-backend/math_learn/.idea/misc.xml @@ -1,13 +1,5 @@ - - - - diff --git a/src/java-backend/math_learn/.idea/modules.xml b/src/java-backend/math_learn/.idea/modules.xml new file mode 100644 index 0000000..422d56a --- /dev/null +++ b/src/java-backend/math_learn/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/java-backend/math_learn/META-INF/MANIFEST.MF b/src/java-backend/math_learn/META-INF/MANIFEST.MF deleted file mode 100644 index 0054b90..0000000 --- a/src/java-backend/math_learn/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: com.mathlearn.Main - diff --git a/src/java-backend/math_learn/math-learning-system.iml b/src/java-backend/math_learn/math-learning-system.iml deleted file mode 100644 index abe781f..0000000 --- a/src/java-backend/math_learn/math-learning-system.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/pom.xml b/src/java-backend/math_learn/pom.xml deleted file mode 100644 index f031ea9..0000000 --- a/src/java-backend/math_learn/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - 4.0.0 - - com.mathlearn - math-learning-system - 1.0.0 - - - 8 - 8 - UTF-8 - - - - - - com.sun.mail - javax.mail - 1.6.2 - - - - - javax.activation - activation - 1.1.1 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 9 - 9 - - - - - \ No newline at end of file diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class new file mode 100644 index 0000000..353bdc3 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$BaseHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class new file mode 100644 index 0000000..b5329c7 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$ChangePasswordHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$FinishExamHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$FinishExamHandler.class new file mode 100644 index 0000000..37e6049 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$FinishExamHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class new file mode 100644 index 0000000..293b2db Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$GenerateExamHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$GetQuestionHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$GetQuestionHandler.class new file mode 100644 index 0000000..84b98c3 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$GetQuestionHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class new file mode 100644 index 0000000..b1499ea Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$LoginHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class new file mode 100644 index 0000000..b371211 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$LogoutHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class new file mode 100644 index 0000000..de3d754 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$RegisterHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class new file mode 100644 index 0000000..e2419eb Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$SendRegistrationCodeHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class b/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class new file mode 100644 index 0000000..bf68e84 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main$SubmitAnswerHandler.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.class b/src/java-backend/math_learn/src/com/mathlearn/Main.class new file mode 100644 index 0000000..cd98b8c Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/Main.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/Main.java b/src/java-backend/math_learn/src/com/mathlearn/Main.java index 7d330cf..543d29a 100644 --- a/src/java-backend/math_learn/src/com/mathlearn/Main.java +++ b/src/java-backend/math_learn/src/com/mathlearn/Main.java @@ -8,15 +8,13 @@ import com.mathlearn.model.user.UserAccount; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; + import java.io.*; import java.net.InetSocketAddress; import java.text.SimpleDateFormat; import java.util.*; -import javax.mail.*; -import javax.mail.internet.*; -import java.util.Properties; -// 主系统类 - 改造为->HTTP服务器 +// 主系统类 - 改造为HTTP服务器 public class Main { private Map accounts; private Map pendingRegistrations; // 待完成注册的用户 @@ -25,13 +23,6 @@ public class Main { private String baseDirectory = "math_questions"; private Random random = new Random(); - // 邮件配置 - 请修改为你的QQ邮箱信息 - private static final String EMAIL_HOST = "smtp.qq.com"; - private static final String EMAIL_PORT = "587"; - private static final String EMAIL_USERNAME = "2944528150@qq.com"; // QQ邮箱 - private static final String EMAIL_PASSWORD = "kxfeaqqfyxysdhfh"; // QQ邮箱授权码,不是密码 - private static final String EMAIL_FROM = "2944528150@qq.com"; // 发件人邮箱 - public Main() { initializeAccounts(); pendingRegistrations = new HashMap<>(); @@ -112,7 +103,7 @@ public class Main { System.out.println("注册成功: " + username); return new ApiResponse(true, "注册成功", null); } - //添加发送注册码的方法 + // 在math_question类中添加发送注册码的方法 public ApiResponse sendRegistrationCode(String email) { System.out.println("收到发送注册码请求,邮箱: " + email); @@ -131,19 +122,18 @@ public class Main { // 生成注册码 String code = generateRegistrationCode(email); - // 发送邮件 - boolean emailSent = sendEmail(email, "数学学习系统 - 注册验证码", - buildEmailContent(code)); + // 模拟发送邮件 + System.out.println("=== 邮件发送模拟 ==="); + System.out.println("收件人: " + email); + System.out.println("验证码: " + code); + System.out.println("=== 邮件发送完成 ==="); - if (emailSent) { - Map data = new HashMap<>(); - data.put("email", email); - // 实际生产环境中不应该返回验证码,这里仅用于测试 - data.put("debugCode", code); - return new ApiResponse(true, "验证码已发送到您的邮箱", data); - } else { - return new ApiResponse(false, "邮件发送失败,请检查邮箱地址或稍后重试", null); - } + Map data = new HashMap<>(); + data.put("email", email); + // 注意:实际生产中不应该返回验证码,这里仅用于演示和测试 + data.put("debugCode", code); + + return new ApiResponse(true, "验证码已发送到您的邮箱", data); } // 验证邮箱格式 @@ -154,75 +144,7 @@ public class Main { } - // 构建邮件内容 - private String buildEmailContent(String code) { - return "" + - "" + - "" + - "" + - "" + - "" + - "" + - "
" + - "

数学学习系统 - 注册验证码

" + - "

您好!

" + - "

您正在注册数学学习系统账号,验证码为:

" + - "
" + code + "
" + - "

验证码有效期15分钟,请尽快完成注册。

" + - "

如非本人操作,请忽略此邮件。

" + - "
" + - "

数学学习系统团队

" + - "

此为系统邮件,请勿回复

" + - "
" + - "
" + - "" + - ""; - } - // 发送邮件方法 - private boolean sendEmail(String toEmail, String subject, String content) { - try { - // 配置邮件服务器属性 - Properties props = new Properties(); - props.put("mail.smtp.auth", "true"); - props.put("mail.smtp.starttls.enable", "true"); - props.put("mail.smtp.host", EMAIL_HOST); - props.put("mail.smtp.port", EMAIL_PORT); - props.put("mail.smtp.ssl.trust", EMAIL_HOST); - - // 创建会话 - Session session = Session.getInstance(props, new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(EMAIL_USERNAME, EMAIL_PASSWORD); - } - }); - - // 创建邮件 - Message message = new MimeMessage(session); - message.setFrom(new InternetAddress(EMAIL_FROM)); - message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); - message.setSubject(subject); - - // 设置邮件内容为HTML格式 - message.setContent(content, "text/html; charset=utf-8"); - - // 发送邮件 - Transport.send(message); - System.out.println("邮件发送成功 - 收件人: " + toEmail); - return true; - - } catch (Exception e) { - System.err.println("邮件发送失败: " + e.getMessage()); - e.printStackTrace(); - return false; - } - } // 验证密码格式 private boolean isValidPassword(String password) { @@ -549,24 +471,13 @@ public class Main { server.createContext("/api/submit-answer", new SubmitAnswerHandler()); server.createContext("/api/finish-exam", new FinishExamHandler()); server.createContext("/api/logout", new LogoutHandler()); - - // 添加这一行 - 注册发送注册码的端点 + // 添加新的注册码相关端点 server.createContext("/api/send-registration-code", new SendRegistrationCodeHandler()); server.setExecutor(null); server.start(); System.out.println("数学学习系统服务器已启动,端口: " + port); - System.out.println("已注册的端点:"); - System.out.println(" - /api/register"); - System.out.println(" - /api/login"); - System.out.println(" - /api/change-password"); - System.out.println(" - /api/generate-exam"); - System.out.println(" - /api/get-question"); - System.out.println(" - /api/submit-answer"); - System.out.println(" - /api/finish-exam"); - System.out.println(" - /api/logout"); - System.out.println(" - /api/send-registration-code"); // 确认这个端点已注册 } // 内部HTTP处理器类 diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class new file mode 100644 index 0000000..83e17f3 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java index 4646e1b..f10929e 100644 --- a/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java +++ b/src/java-backend/math_learn/src/com/mathlearn/generator/JuniorHighGenerator.java @@ -16,9 +16,8 @@ public class JuniorHighGenerator implements QuestionGenerator { switch (type) { case 0: // 基本四则运算(考虑优先级) - ExpressionResult exprResult = generateArithmeticQuestion(); - questionText = exprResult.expression; - correctAnswerValue = exprResult.value; + questionText = generateArithmeticQuestion(); + correctAnswerValue = evaluateExpression(questionText.replace(" = ?", "")); isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue); break; @@ -62,143 +61,48 @@ public class JuniorHighGenerator implements QuestionGenerator { return new Question(questionText, options, correctIndex); } - // 表达式和结果封装类 - private static class ExpressionResult { - String expression; - double value; - - ExpressionResult(String expression, double value) { - this.expression = expression; - this.value = value; - } - } - - // 生成考虑优先级的算术题目并同时计算结果 - private ExpressionResult generateArithmeticQuestion() { - // 使用预定义的简单表达式模板,确保可计算 - String[][] templates = { - {"%d + %d × %d", "先乘后加"}, - {"%d × %d + %d", "先乘后加"}, - {"%d - %d × %d", "先乘后减"}, - {"%d × %d - %d", "先乘后减"}, - {"%d + %d ÷ %d", "先除后加"}, - {"%d ÷ %d + %d", "先除后加"}, - {"%d - %d ÷ %d", "先除后减"}, - {"%d ÷ %d - %d", "先除后减"}, - {"%d × (%d + %d)", "先加后乘"}, - {"(%d + %d) × %d", "先加后乘"}, - {"%d × (%d - %d)", "先减后乘"}, - {"(%d - %d) × %d", "先减后乘"} - }; - - String[] template = templates[random.nextInt(templates.length)]; - String pattern = template[0]; - String description = template[1]; - - // 生成合适的数字,确保计算有效 - int a, b, c = 1; - double result = 0; - - // 根据模板类型生成合适的数字 - if (pattern.contains("÷")) { - // 除法模板:确保除数不为0且能整除 - if (pattern.startsWith("%d ÷")) { - // 第一个操作数是除法:确保b能整除a - b = random.nextInt(9) + 1; // 1-9 - a = b * (random.nextInt(5) + 1); // a是b的倍数 - c = random.nextInt(10) + 1; - result = (double)a / b + (pattern.contains("+") ? c : -c); - } else if (pattern.contains("÷ %d +") || pattern.contains("÷ %d -")) { - // 其他位置的除法:确保除数不为0 - a = random.nextInt(10) + 1; - b = random.nextInt(9) + 1; // 1-9 - c = random.nextInt(10) + 1; - result = (double)a / b + (pattern.contains("+") ? c : -c); - } else { - // 中间的除法 - a = random.nextInt(10) + 1; - b = random.nextInt(9) + 1; // 1-9 - c = random.nextInt(10) + 1; - if (pattern.contains("+ %d ÷")) { - result = a + (double)b / c; - } else if (pattern.contains("- %d ÷")) { - result = a - (double)b / c; + // 生成考虑优先级的算术题目 + private String generateArithmeticQuestion() { + int operandCount = random.nextInt(3) + 2; // 2-4个操作数 + StringBuilder question = new StringBuilder(); + List tokens = new ArrayList<>(); + + // 生成操作数 + for (int i = 0; i < operandCount; i++) { + if (i > 0) { + // 随机选择运算符,考虑优先级 + String[] availableOps; + if (i == 1 && operandCount > 2) { + // 第一个运算符倾向于用乘除,确保优先级测试 + availableOps = new String[]{"×", "÷", "+", "-"}; + } else { + availableOps = new String[]{"+", "-", "×", "÷"}; } + String op = availableOps[random.nextInt(availableOps.length)]; + tokens.add(op); + question.append(" ").append(op).append(" "); } - } else if (pattern.contains("(")) { - // 括号模板 - a = random.nextInt(10) + 1; - b = random.nextInt(10) + 1; - c = random.nextInt(10) + 1; - if (pattern.contains("× (") && pattern.contains(" + ")) { - result = a * (b + c); - } else if (pattern.contains("× (") && pattern.contains(" - ")) { - result = a * (b - c); - } else if (pattern.contains(" + ") && pattern.contains(") ×")) { - result = (a + b) * c; - } else if (pattern.contains(" - ") && pattern.contains(") ×")) { - result = (a - b) * c; - } - } else { - // 基本四则运算 - a = random.nextInt(10) + 1; - b = random.nextInt(10) + 1; - c = random.nextInt(10) + 1; - - // 根据运算符计算结果 - if (pattern.equals("%d + %d × %d")) { - result = a + b * c; - } else if (pattern.equals("%d × %d + %d")) { - result = a * b + c; - } else if (pattern.equals("%d - %d × %d")) { - result = a - b * c; - } else if (pattern.equals("%d × %d - %d")) { - result = a * b - c; - } - } - // 如果还没有计算结果,使用安全的表达式计算 - if (result == 0) { - result = safeEvaluateExpression(pattern, a, b, c); + // 生成合适的操作数 + int num; + if (tokens.size() > 0 && (tokens.get(tokens.size()-1).equals("÷"))) { + // 除法:生成能整除的数 + num = generateDivisibleNumber(); + } else { + num = random.nextInt(30) + 1; // 1-30 + } + tokens.add(String.valueOf(num)); + question.append(num); } + question.append(" = ?"); - String expression = String.format(pattern, a, b, c) + " = ?"; - - return new ExpressionResult(expression, result); + return question.toString(); } - // 安全的表达式计算 - private double safeEvaluateExpression(String pattern, int a, int b, int c) { - try { - if (pattern.equals("%d + %d × %d")) { - return a + b * c; - } else if (pattern.equals("%d × %d + %d")) { - return a * b + c; - } else if (pattern.equals("%d - %d × %d")) { - return a - b * c; - } else if (pattern.equals("%d × %d - %d")) { - return a * b - c; - } else if (pattern.equals("%d + %d ÷ %d")) { - return a + (double)b / c; - } else if (pattern.equals("%d ÷ %d + %d")) { - return (double)a / b + c; - } else if (pattern.equals("%d - %d ÷ %d")) { - return a - (double)b / c; - } else if (pattern.equals("%d ÷ %d - %d")) { - return (double)a / b - c; - } else if (pattern.equals("%d × (%d + %d)")) { - return a * (b + c); - } else if (pattern.equals("(%d + %d) × %d")) { - return (a + b) * c; - } else if (pattern.equals("%d × (%d - %d)")) { - return a * (b - c); - } else if (pattern.equals("(%d - %d) × %d")) { - return (a - b) * c; - } - } catch (Exception e) { - System.err.println("计算表达式失败: " + String.format(pattern, a, b, c) + ", 错误: " + e.getMessage()); - } - return 0; + // 生成能整除的数(用于除法运算) + private int generateDivisibleNumber() { + int[] smallNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + return smallNumbers[random.nextInt(smallNumbers.length)]; } // 计算简单运算(支持负数) @@ -211,8 +115,66 @@ public class JuniorHighGenerator implements QuestionGenerator { } } + // 计算表达式(考虑运算优先级)- 使用自定义解析器避免ScriptEngine问题 + private double evaluateExpression(String expression) { + try { + // 移除空格 + expression = expression.replaceAll(" ", ""); + + // 使用递归下降解析器计算表达式 + return evaluate(expression); + } catch (Exception e) { + System.err.println("计算表达式失败: " + expression + ", 错误: " + e.getMessage()); + return 0; + } + } + + // 递归计算表达式 + private double evaluate(String expr) { + if (expr.isEmpty()) return 0; + + // 处理加减法 + String[] plusMinus = expr.split("(?=[+-])", 2); + if (plusMinus.length > 1) { + double left = evaluate(plusMinus[0]); + double right = evaluate(plusMinus[1].substring(1)); + return plusMinus[1].charAt(0) == '+' ? left + right : left - right; + } + + // 处理乘除法 + String[] multDiv = expr.split("(?=[×÷])", 2); + if (multDiv.length > 1) { + double left = evaluateTerm(multDiv[0]); + double right = evaluateTerm(multDiv[1].substring(1)); + return multDiv[1].charAt(0) == '×' ? left * right : left / right; + } + + // 处理基本项(数字或括号表达式) + return evaluateTerm(expr); + } + + // 计算基本项 + private double evaluateTerm(String term) { + if (term.startsWith("(") && term.endsWith(")")) { + return evaluate(term.substring(1, term.length() - 1)); + } + + // 处理平方符号 + if (term.endsWith("²")) { + double base = evaluateTerm(term.substring(0, term.length() - 1)); + return base * base; + } + + try { + return Double.parseDouble(term); + } catch (NumberFormatException e) { + System.err.println("解析数字失败: " + term); + return 0; + } + } + private int getPerfectSquare() { - int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144}; + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; return perfectSquares[random.nextInt(perfectSquares.length)]; } @@ -228,51 +190,32 @@ public class JuniorHighGenerator implements QuestionGenerator { used.add(correctStr); // 生成3个错误选项 - int attempts = 0; - while (options.size() < 4 && attempts < 50) { - attempts++; + while (options.size() < 4) { double wrongValue; String wrongStr; - // 根据正确答案调整变化范围 - double baseRange = Math.max(2, Math.abs(correctAnswer) * 0.3); - double variation = (random.nextDouble() * baseRange) + 1; - boolean positive = random.nextBoolean(); - - wrongValue = correctAnswer + (positive ? variation : -variation); - - if (isInteger) { - wrongValue = Math.round(wrongValue); - wrongStr = String.valueOf((int)wrongValue); - } else { - wrongValue = Math.round(wrongValue * 100) / 100.0; - wrongStr = String.format("%.2f", wrongValue); - } + do { + // 根据正确答案的大小调整变化范围 + double range = Math.max(5, Math.abs(correctAnswer) * 0.3); + double variation = (random.nextDouble() * range) + 1; + boolean positive = random.nextBoolean(); - if (!used.contains(wrongStr)) { - options.add(wrongStr); - used.add(wrongStr); - } - } + wrongValue = correctAnswer + (positive ? variation : -variation); - // 如果选项不够,添加一些固定选项 - while (options.size() < 4) { - String extraOption; - if (isInteger) { - int extraValue = (int)correctAnswer + options.size() * 2 + 1; - extraOption = String.valueOf(extraValue); - } else { - double extraValue = correctAnswer + options.size() * 0.5 + 0.1; - extraOption = String.format("%.2f", extraValue); - } + if (isInteger) { + wrongValue = Math.round(wrongValue); + wrongStr = String.valueOf((int)wrongValue); + } else { + wrongValue = Math.round(wrongValue * 100) / 100.0; + wrongStr = String.format("%.2f", wrongValue); + } + } while (used.contains(wrongStr) || Double.isNaN(wrongValue) || Double.isInfinite(wrongValue)); - if (!used.contains(extraOption)) { - options.add(extraOption); - used.add(extraOption); - } + options.add(wrongStr); + used.add(wrongStr); } Collections.shuffle(options); return options; } -} \ No newline at end of file +} diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class new file mode 100644 index 0000000..bbca5cb Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/generator/PrimarySchoolGenerator.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class new file mode 100644 index 0000000..2bfb7d7 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/generator/QuestionGenerator.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator$ExpressionResult.class b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator$ExpressionResult.class new file mode 100644 index 0000000..aab609d Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator$ExpressionResult.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class new file mode 100644 index 0000000..4967054 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/generator/SeniorHighGenerator.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class new file mode 100644 index 0000000..77c835a Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/generator/StableQuestionGenerator.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class new file mode 100644 index 0000000..649edee Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/model/api/ApiResponse.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class new file mode 100644 index 0000000..fa6df17 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Exam.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class new file mode 100644 index 0000000..8942b24 Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/model/exam/Question.class differ diff --git a/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class new file mode 100644 index 0000000..d02c2fa Binary files /dev/null and b/src/java-backend/math_learn/src/com/mathlearn/model/user/UserAccount.class differ