第一次修改

pull/1/head
张豪 7 months ago
parent fdbc214f27
commit fb357ca552

@ -1,2 +0,0 @@
# Pair-Programming

File diff suppressed because it is too large Load Diff

@ -1,34 +0,0 @@
{
"name": "math-learning-app",
"version": "1.0.0",
"description": "小初高数学学习软件",
"main": "src/main.js",
"scripts": {
"start": "electron .",
"dev": "electron . --dev",
"build": "electron-builder"
},
"devDependencies": {
"electron": "^22.0.0",
"electron-builder": "^24.0.0"
},
"build": {
"appId": "com.mathlearning.app",
"productName": "数学学习系统",
"directories": {
"output": "dist"
},
"files": [
"src/**/*",
"styles/**/*",
"assets/**/*"
],
"win": {
"target": "nsis",
"icon": "assets/icon.ico"
}
},
"dependencies": {
"node-fetch": "^2.7.0"
}
}

@ -1,100 +0,0 @@
const fetch = require('node-fetch');
const { app, BrowserWindow, Menu, ipcMain } = require('electron');
const path = require('path');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js'), // 确保路径正确
webSecurity: false // 开发时可以关闭避免CORS问题
},
icon: path.join(__dirname, 'assets/icon.png') // 可选
});
// 加载登录页面
mainWindow.loadFile(path.join(__dirname, 'renderer/login.html'));
// 开发时打开开发者工具
mainWindow.webContents.openDevTools();
}
function createMenu() {
const template = [
{
label: '文件',
submenu: [
{
label: '退出',
click: () => app.quit()
}
]
},
{
label: '查看',
submenu: [
{ role: 'reload' },
{ role: 'toggleDevTools' }
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}
// API 基础URL
const API_BASE_URL = 'http://localhost:8080/api';
// 处理API请求
ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = {} }) => {
try {
const url = `${API_BASE_URL}${endpoint}`;
const formData = new URLSearchParams();
for (const [key, value] of Object.entries(data)) {
formData.append(key, value);
}
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData
});
const result = await response.json();
return result;
} catch (error) {
return {
success: false,
message: `网络错误: ${error.message}`,
data: null
};
}
});
// 页面导航
ipcMain.handle('navigate-to', (event, page) => {
mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`));
});
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});

@ -1,129 +0,0 @@
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),
// 存储会话数据
setSession: (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
},
getSession: (key) => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
},
removeSession: (key) => {
localStorage.removeItem(key);
},
// 新增:获取当前会话状态
getSessionState: () => {
return SessionManager.validateSession();
},
// 新增:强制清除所有会话
clearAllSessions: () => {
SessionManager.clearAllSessions();
},
// 新增会话验证方法
validateSession: () => {
return SessionManager.validateUserSession();
},
// 新增会话刷新方法
refreshSession: (userData) => {
SessionManager.refreshUserSession(userData);
}
});
// 直接在渲染进程中暴露 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();
for (const [key, value] of Object.entries(data)) {
formData.append(key, value);
}
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData
});
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}`,
data: null
};
}
}
});
console.log('Preload script loaded successfully');

@ -1,119 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数学试卷自动生成系统 - 登录</title>
<link rel="stylesheet" href="../style/common.css">
<style>
.login-container {
max-width: 400px;
margin: 100px auto;
padding: 40px;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
}
input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
}
button {
width: 100%;
padding: 12px;
background: #007acc;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: #005a9e;
}
.link {
color: #007acc;
cursor: pointer;
text-align: center;
display: block;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="login-container">
<h2>数学试卷自动生成系统</h2>
<form id="loginForm">
<div class="form-group">
<input type="text" id="username" placeholder="用户名" required>
</div>
<div class="form-group">
<input type="password" id="password" placeholder="密码" required>
</div>
<button type="submit">登录</button>
</form>
<span class="link" id="registerLink">没有账号?立即注册</span>
<div id="message" class="message"></div>
</div>
<script>
// 页面加载完成后自动聚焦到用户名输入框
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
const usernameInput = document.getElementById('username');
if (usernameInput) {
// 强制触发重绘
usernameInput.style.display = 'none';
usernameInput.offsetHeight; // 触发回流
usernameInput.style.display = '';
// 设置焦点
usernameInput.focus();
}
}, 100);
});
document.getElementById('loginForm').addEventListener('submit', async (e) => {
// 原有登录逻辑保持不变...
e.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const messageEl = document.getElementById('message');
const result = await window.api.request('/login', 'POST', {
username, password
});
if (result.success) {
window.electronAPI.setSession('userSession', {
sessionId: result.data.sessionId,
username: result.data.username,
userType: result.data.userType
});
await window.electronAPI.navigateTo('main');
} else {
messageEl.textContent = result.message;
messageEl.className = 'message error';
}
});
document.getElementById('registerLink').addEventListener('click', async () => {
await window.electronAPI.navigateTo('register');
});
</script>
</body>
</html>

@ -1,432 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数学学习系统 - 主页</title>
<link rel="stylesheet" href="../style/common.css">
<style>
.main-container {
max-width: 600px;
margin: 50px auto;
padding: 40px;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
.user-info {
background: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 30px;
}
.btn-group {
display: flex;
gap: 15px;
margin-bottom: 20px;
}
.exam-settings {
margin-top: 30px;
}
input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
margin-bottom: 15px;
}
</style>
</head>
<body>
<div class="main-container">
<h2>数学学习系统</h2>
<div class="user-info" id="userInfo">
<!-- 用户信息将通过JavaScript填充 -->
</div>
<div class="btn-group">
<button class="btn btn-primary" data-type="小学">小学题目</button>
<button class="btn btn-success" data-type="初中">初中题目</button>
<button class="btn btn-warning" data-type="高中">高中题目</button>
</div>
<div class="exam-settings" id="examSettings" style="display: none;">
<h3>生成 <span id="selectedType"></span> 题目</h3>
<input type="number" id="questionCount" placeholder="题目数量 (10-30)" min="10" max="30">
<button class="btn btn-primary" id="startExam">开始答题</button>
</div>
<div style="margin-top: 30px;">
<button class="btn btn-danger" id="logoutBtn">退出登录</button>
<button class="btn btn-warning" id="changePasswordBtn">修改密码</button>
</div>
</div>
<script>
let currentUser = null;
let selectedType = null;
document.addEventListener('DOMContentLoaded', async () => {
// 获取当前用户信息
currentUser = window.electronAPI.getSession('userSession');
if (!currentUser) {
await window.electronAPI.navigateTo('login');
return;
}
// 显示用户信息
document.getElementById('userInfo').innerHTML = `
<strong>用户名:</strong> ${currentUser.username}<br>
<strong>用户类型:</strong> ${currentUser.userType}
`;
// 绑定题目类型按钮事件
document.querySelectorAll('.btn-group button').forEach(btn => {
btn.addEventListener('click', (e) => {
selectedType = e.target.dataset.type;
document.getElementById('selectedType').textContent = selectedType;
document.getElementById('examSettings').style.display = 'block';
});
});
// 绑定开始答题按钮事件
const startExamBtn = document.getElementById('startExam');
if (startExamBtn) {
startExamBtn.addEventListener('click', startExam);
}
// 绑定退出登录按钮
const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) {
logoutBtn.addEventListener('click', logout);
}
// 绑定修改密码按钮
const changePasswordBtn = document.getElementById('changePasswordBtn');
if (changePasswordBtn) {
changePasswordBtn.addEventListener('click', showChangePasswordModal);
}
});
async function startExam() {
console.log('=== 开始答题流程开始 ===');
const questionCount = parseInt(document.getElementById('questionCount').value);
if (!selectedType) {
alert('请先选择题目类型');
return;
}
if (isNaN(questionCount) || questionCount < 10 || questionCount > 30) {
alert('题目数量应在10-30之间');
return;
}
try {
// 重新获取最新用户会话
const latestUser = window.electronAPI.getSession('userSession');
console.log('当前用户会话:', latestUser);
if (!latestUser || !latestUser.sessionId) {
alert('用户会话已过期,请重新登录');
await window.electronAPI.navigateTo('login');
return;
}
console.log('开始生成试卷请求:', {
sessionId: latestUser.sessionId,
userType: selectedType,
questionCount: questionCount
});
// 显示加载状态
const startExamBtn = document.getElementById('startExam');
const originalText = startExamBtn.textContent;
startExamBtn.textContent = '生成中...';
startExamBtn.disabled = true;
console.log('发送生成试卷请求...');
// 添加超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 15000); // 15秒超时
try {
const result = await window.api.request('/generate-exam', 'POST', {
sessionId: latestUser.sessionId,
userType: selectedType,
questionCount: questionCount
});
clearTimeout(timeoutId);
console.log('生成试卷API响应:', result);
if (result.success) {
// 保存考试信息 - 确保包含所有必要字段
const examData = {
examId: result.data.examId,
totalQuestions: result.data.totalQuestions,
currentQuestion: result.data.currentQuestion || 0,
userType: selectedType,
// 保存第一题的详细信息,确保跳转后能立即显示
firstQuestion: {
question: result.data.question,
options: result.data.options
}
};
console.log('保存考试数据:', examData);
window.electronAPI.setSession('currentExam', examData);
// 确保数据保存完成后再跳转
setTimeout(async () => {
console.log('考试数据已保存,准备跳转到答题页面');
await window.electronAPI.navigateTo('quiz');
}, 100);
} else {
alert('生成试卷失败: ' + result.message);
// 如果是会话问题,清除会话
if (result.message.includes('会话') || result.message.includes('登录')) {
window.electronAPI.removeSession('userSession');
await window.electronAPI.navigateTo('login');
}
}
} catch (fetchError) {
clearTimeout(timeoutId);
throw fetchError;
}
} catch (error) {
console.error('生成试卷错误:', error);
if (error.name === 'AbortError') {
alert('请求超时!请检查:\n1. 后端Java程序是否运行\n2. 网络连接是否正常\n3. 端口8080是否被占用');
} else {
alert('生成试卷时发生错误: ' + error.message);
}
} finally {
// 恢复按钮状态
const startExamBtn = document.getElementById('startExam');
if (startExamBtn) {
startExamBtn.textContent = '开始答题';
startExamBtn.disabled = false;
}
}
console.log('=== 开始答题流程结束 ===');
}
// 网络连接测试函数
async function testBackendConnectivity() {
try {
console.log('测试后端连接...');
// 使用更简单的请求测试连接
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000);
const response = await fetch('http://localhost:8080/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'username=test&password=test',
signal: controller.signal
});
clearTimeout(timeoutId);
return {
connected: true,
status: response.status
};
} catch (error) {
console.error('网络连接测试失败:', error);
return {
connected: false,
error: error.message
};
}
}
async function logout() {
if (confirm('确定要退出登录吗?')) {
try {
// 获取最新用户会话
const latestUser = window.electronAPI.getSession('userSession');
console.log('退出登录,用户信息:', latestUser);
if (latestUser && latestUser.sessionId) {
console.log('发送退出登录请求sessionId:', latestUser.sessionId);
const result = await window.api.request('/logout', 'POST', {
sessionId: latestUser.sessionId
});
console.log('退出登录响应:', result);
} else {
console.log('没有有效的用户会话,直接清除本地数据');
}
} catch (error) {
console.error('退出登录API错误:', error);
// 即使API失败也继续清除本地数据
} finally {
// 清除所有本地存储
window.electronAPI.removeSession('userSession');
window.electronAPI.removeSession('currentExam');
window.electronAPI.removeSession('examResult');
console.log('本地会话已清除,跳转到登录页面');
// 直接跳转
await window.electronAPI.navigateTo('login');
}
}
}
// 显示修改密码模态框
function showChangePasswordModal() {
// 创建修改密码模态框
const modalHtml = `
<div id="passwordModal" style="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;">
<div style="background:white;padding:30px;border-radius:10px;width:400px;" id="passwordModalContent">
<h3>修改密码</h3>
<div class="form-group">
<input type="password" id="oldPassword" placeholder="原密码" style="width:100%;padding:10px;margin:10px 0;">
</div>
<div class="form-group">
<input type="password" id="newPassword" placeholder="新密码" style="width:100%;padding:10px;margin:10px 0;">
</div>
<div class="form-group">
<input type="password" id="confirmPassword" placeholder="确认新密码" style="width:100%;padding:10px;margin:10px 0;">
</div>
<div style="display:flex;gap:10px;margin-top:20px;">
<button id="confirmChangePassword" class="btn btn-primary" style="flex:1;">确认修改</button>
<button id="cancelChangePassword" class="btn btn-secondary" style="flex:1;">取消</button>
</div>
<div id="passwordMessage" style="margin-top:10px;"></div>
</div>
</div>
`;
// 添加模态框到页面
document.body.insertAdjacentHTML('beforeend', modalHtml);
// 绑定模态框事件 - 阻止内容区域点击事件冒泡
const modalContent = document.getElementById('passwordModalContent');
modalContent.addEventListener('click', function (e) {
e.stopPropagation();
});
// 绑定按钮事件
document.getElementById('confirmChangePassword').addEventListener('click', changePassword);
document.getElementById('cancelChangePassword').addEventListener('click', closePasswordModal);
// 点击模态框背景关闭
document.getElementById('passwordModal').addEventListener('click', function (e) {
if (e.target === this) {
closePasswordModal();
}
});
// 自动聚焦到第一个输入框
setTimeout(() => {
document.getElementById('oldPassword').focus();
}, 100);
}
// 关闭修改密码模态框
function closePasswordModal() {
const modal = document.getElementById('passwordModal');
if (modal) {
modal.remove();
}
}
async function changePassword() {
const oldPassword = document.getElementById('oldPassword').value;
const newPassword = document.getElementById('newPassword').value;
const confirmPassword = document.getElementById('confirmPassword').value;
const messageEl = document.getElementById('passwordMessage');
// 清空之前的消息
messageEl.textContent = '';
messageEl.style.color = '';
if (!oldPassword || !newPassword || !confirmPassword) {
messageEl.textContent = '请填写所有字段';
messageEl.style.color = 'red';
return;
}
if (newPassword !== confirmPassword) {
messageEl.textContent = '两次输入的新密码不一致';
messageEl.style.color = 'red';
return;
}
try {
// 重新获取最新用户会话
const latestUser = window.electronAPI.getSession('userSession');
console.log('修改密码,用户信息:', latestUser);
if (!latestUser || !latestUser.sessionId) {
messageEl.textContent = '用户会话已过期,请重新登录';
messageEl.style.color = 'red';
setTimeout(() => {
closePasswordModal();
window.electronAPI.navigateTo('login');
}, 2000);
return;
}
const result = await window.api.request('/change-password', 'POST', {
sessionId: latestUser.sessionId,
oldPassword: oldPassword,
newPassword: newPassword,
confirmPassword: confirmPassword
});
console.log('修改密码响应:', result);
if (result.success) {
messageEl.textContent = '密码修改成功';
messageEl.style.color = 'green';
// 更新本地会话中的密码信息(如果需要)
// 注意:这里只更新本地显示,实际密码已在后端更新
setTimeout(() => {
closePasswordModal();
}, 2000);
} else {
messageEl.textContent = result.message;
messageEl.style.color = 'red';
// 如果是会话问题,清除会话
if (result.message.includes('会话') || result.message.includes('登录')) {
window.electronAPI.removeSession('userSession');
setTimeout(() => {
closePasswordModal();
window.electronAPI.navigateTo('login');
}, 2000);
}
}
} catch (error) {
console.error('修改密码错误:', error);
messageEl.textContent = '修改密码时发生错误: ' + error.message;
messageEl.style.color = 'red';
}
}
</script>
</body>
</html>

@ -1,264 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数学学习系统 - 答题</title>
<link rel="stylesheet" href="../style/common.css">
<style>
.quiz-container {
max-width: 800px;
margin: 20px auto;
padding: 30px;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
.progress {
margin-bottom: 30px;
}
.question {
font-size: 20px;
margin-bottom: 30px;
line-height: 1.6;
}
.options {
margin-bottom: 30px;
}
.option {
display: block;
padding: 15px;
margin-bottom: 10px;
border: 2px solid #ddd;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s;
}
.option:hover {
background: #f8f9fa;
}
.option.selected {
border-color: #007acc;
background: #e7f3ff;
}
.navigation {
display: flex;
justify-content: space-between;
}
button {
padding: 12px 24px;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}
.prev {
background: #6c757d;
color: white;
}
.next {
background: #007acc;
color: white;
}
.submit {
background: #28a745;
color: white;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
</style>
</head>
<body>
<div class="quiz-container">
<div class="progress" id="progress">
<!-- 进度信息将通过JavaScript填充 -->
</div>
<div class="question" id="question">
<!-- 题目内容将通过JavaScript填充 -->
</div>
<div class="options" id="options">
<!-- 选项将通过JavaScript填充 -->
</div>
<div class="navigation">
<button class="prev" id="prevBtn">上一题</button>
<button class="next" id="nextBtn">下一题</button>
<button class="submit" id="submitBtn" style="display: none;">提交答案</button>
</div>
</div>
<script>
let currentUser = null;
let currentExam = null;
let currentQuestionIndex = 0;
document.addEventListener('DOMContentLoaded', async () => {
currentUser = window.electronAPI.getSession('userSession');
currentExam = window.electronAPI.getSession('currentExam');
if (!currentUser || !currentExam) {
await window.electronAPI.navigateTo('main');
return;
}
currentQuestionIndex = currentExam.currentQuestion || 0;
await loadQuestion(currentQuestionIndex);
// 绑定事件
document.getElementById('prevBtn').addEventListener('click', () => {
if (currentQuestionIndex > 0) {
currentQuestionIndex--;
loadQuestion(currentQuestionIndex);
}
});
document.getElementById('nextBtn').addEventListener('click', () => {
if (currentQuestionIndex < currentExam.totalQuestions - 1) {
currentQuestionIndex++;
loadQuestion(currentQuestionIndex);
}
});
document.getElementById('submitBtn').addEventListener('click', async () => {
const result = await window.api.request('/finish-exam', 'POST', {
sessionId: currentUser.sessionId
});
if (result.success) {
window.electronAPI.setSession('examResult', result.data);
window.electronAPI.removeSession('currentExam');
await window.electronAPI.navigateTo('result');
} else {
alert('提交失败: ' + result.message);
}
});
});
async function loadQuestion(index) {
try {
console.log(`加载第 ${index + 1} 题,用户会话:`, currentUser);
const result = await window.api.request('/get-question', 'POST', {
sessionId: currentUser.sessionId,
questionIndex: index
});
console.log('获取题目响应:', result);
if (result.success) {
// 更新进度
document.getElementById('progress').innerHTML = `
<strong>第 ${index + 1} 题 / 共 ${result.data.totalQuestions} 题</strong>
<br><small>考试ID: ${result.data.examId}</small>
`;
// 显示题目
const questionEl = document.getElementById('question');
questionEl.innerHTML = `<strong>题目 ${index + 1}:</strong> ${result.data.question}`;
// 显示选项
const optionsContainer = document.getElementById('options');
optionsContainer.innerHTML = '';
if (!result.data.options || result.data.options.length === 0) {
optionsContainer.innerHTML = '<div class="option">暂无选项</div>';
return;
}
result.data.options.forEach((option, i) => {
const optionEl = document.createElement('div');
optionEl.className = 'option';
optionEl.innerHTML = `
<strong>${String.fromCharCode(65 + i)}.</strong> ${option}
`;
// 检查是否是当前选中的答案
if (result.data.userAnswer === i) {
optionEl.classList.add('selected');
}
optionEl.addEventListener('click', async () => {
console.log(`用户选择选项 ${i}: ${option}`);
// 移除其他选项的选中状态
document.querySelectorAll('.option').forEach(opt => {
opt.classList.remove('selected');
});
// 选中当前选项
optionEl.classList.add('selected');
try {
// 提交答案
const submitResult = await window.api.request('/submit-answer', 'POST', {
sessionId: currentUser.sessionId,
questionIndex: index,
answerIndex: i
});
console.log('提交答案响应:', submitResult);
if (!submitResult.success) {
console.error('提交答案失败:', submitResult.message);
// 回退选中状态
optionEl.classList.remove('selected');
}
} catch (error) {
console.error('提交答案错误:', error);
// 回退选中状态
optionEl.classList.remove('selected');
}
});
optionsContainer.appendChild(optionEl);
});
// 更新导航按钮状态
document.getElementById('prevBtn').disabled = index === 0;
document.getElementById('nextBtn').style.display =
index < result.data.totalQuestions - 1 ? 'inline-block' : 'none';
document.getElementById('submitBtn').style.display =
index === result.data.totalQuestions - 1 ? 'inline-block' : 'none';
// 保存当前题目索引
currentExam.currentQuestion = index;
window.electronAPI.setSession('currentExam', currentExam);
console.log(`第 ${index + 1} 题加载完成`);
} else {
console.error('加载题目失败:', result.message);
alert('加载题目失败: ' + result.message);
// 如果是会话问题,跳转到登录页
if (result.message.includes('会话') || result.message.includes('登录')) {
window.electronAPI.removeSession('userSession');
window.electronAPI.removeSession('currentExam');
await window.electronAPI.navigateTo('login');
}
}
} catch (error) {
console.error('加载题目错误:', error);
alert('加载题目时发生错误: ' + error.message);
}
}
</script>
</body>
</html>

@ -1,260 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数学学习系统 - 注册</title>
<link rel="stylesheet" href="../style/common.css">
<style>
.register-container {
max-width: 500px;
margin: 50px auto;
padding: 40px;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
}
input,
select {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
}
button {
width: 100%;
padding: 12px;
background: #28a745;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
margin-bottom: 10px;
}
.secondary {
background: #6c757d;
}
.secondary:hover {
background: #545b62;
}
button:hover {
background: #218838;
}
.code-section {
display: flex;
gap: 10px;
}
.code-section input {
flex: 1;
}
.code-section button {
width: 150px;
}
.countdown {
color: #666;
font-size: 14px;
margin-top: 5px;
}
.timer {
color: #dc3545;
font-weight: bold;
}
</style>
</head>
<body>
<div class="register-container">
<h2>用户注册</h2>
<form id="registerForm">
<div class="form-group">
<input type="email" id="email" placeholder="请输入真实邮箱地址" required>
</div>
<div class="form-group">
<div class="code-section">
<input type="text" id="registrationCode" placeholder="请输入邮箱收到的验证码" required>
<button type="button" id="getCodeBtn" class="secondary">获取验证码</button>
</div>
<div id="countdown" class="countdown" style="display: none;">
验证码已发送,<span id="timer" class="timer">60</span>秒后可以重新获取
</div>
</div>
<div class="form-group">
<input type="text" id="username" placeholder="设置用户名" required>
</div>
<div class="form-group">
<input type="password" id="password" placeholder="设置密码 (6-10位包含大小写字母和数字)" required>
</div>
<div class="form-group">
<input type="password" id="confirmPassword" placeholder="确认密码" required>
</div>
<div class="form-group">
<select id="userType" required>
<option value="">选择用户类型</option>
<option value="小学">小学</option>
<option value="初中">初中</option>
<option value="高中">高中</option>
</select>
</div>
<button type="submit">完成注册</button>
</form>
<button class="secondary" id="backToLogin">返回登录</button>
<div id="message" class="message"></div>
</div>
<script>
let countdownTimer = null;
let countdownTime = 60;
// 修改前端API请求确保路径正确
document.getElementById('getCodeBtn').addEventListener('click', async () => {
const email = document.getElementById('email').value;
if (!email) {
showMessage('请输入邮箱地址', 'error');
return;
}
// 验证邮箱格式
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
showMessage('请输入有效的邮箱地址', 'error');
return;
}
try {
// 禁用获取验证码按钮
const getCodeBtn = document.getElementById('getCodeBtn');
getCodeBtn.disabled = true;
getCodeBtn.textContent = '发送中...';
// 调用后端API获取验证码 - 使用正确的路径
const result = await window.api.request('/api/send-registration-code', 'POST', {
email: email
});
if (result.success) {
showMessage('验证码已发送到您的邮箱,请查收', 'success');
startCountdown();
} else {
showMessage(result.message || '发送验证码失败', 'error');
getCodeBtn.disabled = false;
getCodeBtn.textContent = '获取验证码';
}
} catch (error) {
console.error('获取验证码错误:', error);
showMessage('网络错误,请检查服务器连接', 'error');
const getCodeBtn = document.getElementById('getCodeBtn');
getCodeBtn.disabled = false;
getCodeBtn.textContent = '获取验证码';
}
});
document.getElementById('registerForm').addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
const registrationCode = document.getElementById('registrationCode').value;
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirmPassword').value;
const userType = document.getElementById('userType').value;
// 表单验证
if (!email || !registrationCode || !username || !password || !confirmPassword || !userType) {
showMessage('请填写所有必填字段', 'error');
return;
}
if (password !== confirmPassword) {
showMessage('两次输入的密码不一致', 'error');
return;
}
// 密码强度验证
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,10}$/;
if (!passwordRegex.test(password)) {
showMessage('密码必须为6-10位且包含大小写字母和数字', 'error');
return;
}
try {
const result = await window.api.request('/api/register', 'POST', {
email, registrationCode, username, password, confirmPassword, userType
});
if (result.success) {
showMessage('注册成功3秒后自动跳转到登录页面', 'success');
setTimeout(() => {
window.electronAPI.navigateTo('login');
}, 3000);
} else {
showMessage(result.message, 'error');
}
} catch (error) {
console.error('注册错误:', error);
showMessage('注册失败,请检查网络连接', 'error');
}
});
document.getElementById('backToLogin').addEventListener('click', async () => {
await window.electronAPI.navigateTo('login');
});
function startCountdown() {
const countdownEl = document.getElementById('countdown');
const timerEl = document.getElementById('timer');
const getCodeBtn = document.getElementById('getCodeBtn');
countdownEl.style.display = 'block';
getCodeBtn.disabled = true;
countdownTimer = setInterval(() => {
countdownTime--;
timerEl.textContent = countdownTime;
if (countdownTime <= 0) {
clearInterval(countdownTimer);
countdownEl.style.display = 'none';
getCodeBtn.disabled = false;
getCodeBtn.textContent = '重新获取验证码';
countdownTime = 60;
}
}, 1000);
}
function showMessage(message, type) {
const messageEl = document.getElementById('message');
messageEl.textContent = message;
messageEl.className = `message ${type}`;
messageEl.style.display = 'block';
// 3秒后自动隐藏成功消息
if (type === 'success') {
setTimeout(() => {
messageEl.style.display = 'none';
}, 3000);
}
}
</script>
</body>
</html>

@ -1,104 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数学学习系统 - 成绩</title>
<link rel="stylesheet" href="../style/common.css">
<style>
.result-container {
max-width: 600px;
margin: 50px auto;
padding: 40px;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
text-align: center;
}
.score {
font-size: 48px;
font-weight: bold;
color: #28a745;
margin: 20px 0;
}
.btn-group {
display: flex;
gap: 15px;
margin-top: 30px;
}
button {
flex: 1;
padding: 15px;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}
.primary {
background: #007acc;
color: white;
}
.success {
background: #28a745;
color: white;
}
</style>
</head>
<body>
<div class="result-container">
<h2>考试完成</h2>
<div class="score" id="score">
<!-- 分数将通过JavaScript填充 -->
</div>
<p id="resultText"><!-- 结果文本将通过JavaScript填充 --></p>
<div class="btn-group">
<button class="primary" id="continueBtn">继续做题</button>
<button class="success" id="mainBtn">返回主页</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const result = window.electronAPI.getSession('examResult');
if (!result) {
window.electronAPI.navigateTo('main');
return;
}
const score = result.score.toFixed(1);
document.getElementById('score').textContent = `${score}分`;
let resultText = '';
if (score >= 90) {
resultText = '优秀!你做得非常棒!';
} else if (score >= 70) {
resultText = '良好!继续努力!';
} else if (score >= 60) {
resultText = '及格!还有提升空间!';
} else {
resultText = '需要加油哦!多多练习!';
}
document.getElementById('resultText').textContent =
`你在 ${result.totalQuestions} 道题中答对了 ${Math.round(result.totalQuestions * score / 100)} 道题。${resultText}`;
document.getElementById('continueBtn').addEventListener('click', async () => {
await window.electronAPI.navigateTo('main');
});
document.getElementById('mainBtn').addEventListener('click', async () => {
await window.electronAPI.navigateTo('main');
});
});
</script>
</body>
</html>

@ -1,118 +0,0 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.message {
padding: 10px;
margin-top: 15px;
border-radius: 5px;
text-align: center;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.message.info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
/* 基础按钮样式 */
.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;
}

@ -1,6 +0,0 @@
@echo off
echo 启动数学学习系统后端服务器...
cd java-backend
javac math_question.java
java math_question
pause

@ -1,30 +0,0 @@
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
.kotlin
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

@ -1,8 +0,0 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/math_learn.iml" filepath="$PROJECT_DIR$/math_learn.iml" />
</modules>
</component>
</project>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
</component>
</project>

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -1,64 +0,0 @@
考试ID: 20251009192152
考试时间: 2025-10-09 19:21:52
得分: 100.0分
1. 20 ÷ 5 - 3 = ?
A. 9
B. 0
C. 3
D. [正确答案] 1
2. 10 ÷ 5 = ?
A. 12
B. 1
C. 0
D. [正确答案] 2
3. 7 - 7 + 27 = ?
A. 34
B. [正确答案] 27
C. 18
D. 23
4. 48 - 18 = ?
A. 33
B. [正确答案] 30
C. 28
D. 39
5. 10 - 9 = ?
A. [正确答案] 1
B. 10
C. 3
D. 0
6. 2 × 4 × 1 = ?
A. 0
B. 12
C. 4
D. [正确答案] 8
7. 45 + 46 × 1 = ?
A. [正确答案] 91
B. 101
C. 88
D. 89
8. 4 × 1 + 39 = ?
A. 40
B. 45
C. 41
D. [正确答案] 43
9. 28 ÷ 1 = ?
A. [正确答案] 28
B. 33
C. 35
D. 23
10. 47 × 5 = ?
A. 226
B. 243
C. [正确答案] 235
D. 228

@ -1,829 +0,0 @@
package com.mathlearn;
import com.mathlearn.generator.*;
import com.mathlearn.model.api.ApiResponse;
import com.mathlearn.model.exam.Exam;
import com.mathlearn.model.exam.Question;
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.*;
// 主系统类 - 改造为HTTP服务器
public class Main {
private Map<String, UserAccount> accounts;
private Map<String, UserAccount> pendingRegistrations; // 待完成注册的用户
private Map<String, Exam> userExams; // 用户当前试卷
private Map<String, String> userSessions; // 用户会话
private String baseDirectory = "math_questions";
private Random random = new Random();
public Main() {
initializeAccounts();
pendingRegistrations = new HashMap<>();
userExams = new HashMap<>();
userSessions = new HashMap<>();
createBaseDirectory();
}
// 初始化预设账户
private void initializeAccounts() {
accounts = new HashMap<>();
// 小学账号
accounts.put("张三1", new UserAccount("张三1", "Abc123", "小学"));
accounts.put("张三2", new UserAccount("张三2", "Abc123", "小学"));
accounts.put("张三3", new UserAccount("张三3", "Abc123", "小学"));
// 初中账号
accounts.put("李四1", new UserAccount("李四1", "Abc123", "初中"));
accounts.put("李四2", new UserAccount("李四2", "Abc123", "初中"));
accounts.put("李四3", new UserAccount("李四3", "Abc123", "初中"));
// 高中账号
accounts.put("王五1", new UserAccount("王五1", "Abc123", "高中"));
accounts.put("王五2", new UserAccount("王五2", "Abc123", "高中"));
accounts.put("王五3", new UserAccount("王五3", "Abc123", "高中"));
}
// 创建基础目录
private void createBaseDirectory() {
File dir = new File(baseDirectory);
if (!dir.exists()) {
dir.mkdir();
}
}
// 生成注册码
public String generateRegistrationCode(String email) {
String code = "REG" + random.nextInt(10000);
pendingRegistrations.put(email, new UserAccount(email, code));
return code;
}
// 用户注册 - 修改以保存邮箱
public ApiResponse register(String email, String registrationCode, String username, String password, String confirmPassword, String userType) {
System.out.println("处理注册请求: " + username + ", 邮箱: " + email);
// 验证注册码
if (!pendingRegistrations.containsKey(email) ||
!pendingRegistrations.get(email).getRegistrationCode().equals(registrationCode)) {
return new ApiResponse(false, "无效的注册码", null);
}
// 验证用户名是否已存在
if (accounts.containsKey(username)) {
return new ApiResponse(false, "用户名已存在", null);
}
// 验证密码
if (!password.equals(confirmPassword)) {
return new ApiResponse(false, "两次输入的密码不匹配", null);
}
if (!isValidPassword(password)) {
return new ApiResponse(false, "密码必须为6-10位且包含大小写字母和数字", null);
}
// 验证用户类型
if (!userType.equals("小学") && !userType.equals("初中") && !userType.equals("高中")) {
return new ApiResponse(false, "无效的用户类型", null);
}
// 创建用户账户并保存邮箱
UserAccount newAccount = new UserAccount(username, password, userType, email);
accounts.put(username, newAccount);
pendingRegistrations.remove(email);
System.out.println("注册成功: " + username);
return new ApiResponse(true, "注册成功", null);
}
// 在math_question类中添加发送注册码的方法
public ApiResponse sendRegistrationCode(String email) {
System.out.println("收到发送注册码请求,邮箱: " + email);
// 验证邮箱格式
if (!isValidEmail(email)) {
return new ApiResponse(false, "无效的邮箱格式", null);
}
// 检查邮箱是否已注册
for (UserAccount account : accounts.values()) {
if (email.equals(account.getEmail())) {
return new ApiResponse(false, "该邮箱已被注册", null);
}
}
// 生成注册码
String code = generateRegistrationCode(email);
// 模拟发送邮件
System.out.println("=== 邮件发送模拟 ===");
System.out.println("收件人: " + email);
System.out.println("验证码: " + code);
System.out.println("=== 邮件发送完成 ===");
Map<String, Object> data = new HashMap<>();
data.put("email", email);
// 注意:实际生产中不应该返回验证码,这里仅用于演示和测试
data.put("debugCode", code);
return new ApiResponse(true, "验证码已发送到您的邮箱", data);
}
// 验证邮箱格式
private boolean isValidEmail(String email) {
if (email == null) return false;
String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
return email.matches(emailRegex);
}
// 验证密码格式
private boolean isValidPassword(String password) {
if (password.length() < 6 || password.length() > 10) {
return false;
}
boolean hasUpper = false;
boolean hasLower = false;
boolean hasDigit = false;
for (char c : password.toCharArray()) {
if (Character.isUpperCase(c)) hasUpper = true;
if (Character.isLowerCase(c)) hasLower = true;
if (Character.isDigit(c)) hasDigit = true;
}
return hasUpper && hasLower && hasDigit;
}
// 用户登录
public ApiResponse login(String username, String password) {
UserAccount account = accounts.get(username);
if (account != null && account.getPassword().equals(password)) {
// 生成会话ID
String sessionId = generateSessionId();
userSessions.put(sessionId, username);
Map<String, Object> data = new HashMap<>();
data.put("sessionId", sessionId);
data.put("userType", account.getUserType());
data.put("username", username);
return new ApiResponse(true, "登录成功", data);
}
return new ApiResponse(false, "用户名或密码错误", null);
}
// 生成会话ID
private String generateSessionId() {
return "SESS" + System.currentTimeMillis() + random.nextInt(1000);
}
// 验证会话
private String validateSession(String sessionId) {
return userSessions.get(sessionId);
}
// 修改密码
public ApiResponse changePassword(String sessionId, String oldPassword, String newPassword, String confirmPassword) {
String username = validateSession(sessionId);
if (username == null) {
return new ApiResponse(false, "会话无效或已过期", null);
}
UserAccount account = accounts.get(username);
if (!account.getPassword().equals(oldPassword)) {
return new ApiResponse(false, "原密码错误", null);
}
if (!newPassword.equals(confirmPassword)) {
return new ApiResponse(false, "两次输入的新密码不匹配", null);
}
if (!isValidPassword(newPassword)) {
return new ApiResponse(false, "新密码必须为6-10位且包含大小写字母和数字", null);
}
account.setPassword(newPassword);
return new ApiResponse(true, "密码修改成功", null);
}
// 生成试卷 - 添加详细日志
public ApiResponse generateExam(String sessionId, String userType, int questionCount) {
System.out.println("🚀 === 开始生成试卷 ===");
System.out.println("📅 时间: " + new Date());
System.out.println("👤 用户: " + validateSession(sessionId));
System.out.println("🎯 类型: " + userType);
System.out.println("📊 数量: " + questionCount);
try {
String username = validateSession(sessionId);
if (username == null) {
System.out.println("❌ 会话验证失败");
return new ApiResponse(false, "会话无效或已过期", null);
}
if (questionCount < 10 || questionCount > 30) {
return new ApiResponse(false, "题目数量应在10-30之间", null);
}
// 获取题目生成器
QuestionGenerator generator = getQuestionGenerator(userType);
if (generator == null) {
return new ApiResponse(false, "无效的用户类型", null);
}
System.out.println("✅ 开始生成题目...");
// 完全移除去重逻辑,先保证能生成题目
List<Question> questions = new ArrayList<>();
for (int i = 0; i < questionCount; i++) {
System.out.println("🔄 尝试生成第 " + (i + 1) + " 题...");
try {
Question question = generator.generateQuestion();
if (question == null) {
System.out.println("❌ 第 " + (i + 1) + " 题生成返回了null");
continue;
}
questions.add(question);
System.out.println("✅ 第 " + (i + 1) + " 题: " + question.getQuestionText());
System.out.println(" 选项: " + question.getOptions());
System.out.println(" 答案: " + question.getCorrectAnswerIndex());
} catch (Exception e) {
System.err.println("💥 生成第 " + (i + 1) + " 题时发生异常: " + e.getMessage());
e.printStackTrace();
// 继续生成下一题,不要因为一题失败就停止
}
// 添加小延迟,避免快速循环问题
Thread.sleep(50);
}
if (questions.isEmpty()) {
System.err.println("💥 严重错误:一道题目都没有生成成功!");
return new ApiResponse(false, "无法生成任何题目,请检查系统配置", null);
}
System.out.println("🎉 题目生成完成,共 " + questions.size() + " 题");
// 创建试卷
Exam exam = new Exam(questions);
userExams.put(sessionId, exam);
// 返回第一题
Map<String, Object> data = new HashMap<>();
data.put("examId", exam.getExamId());
data.put("totalQuestions", questions.size()); // 使用实际生成的数量
data.put("currentQuestion", 0);
data.put("question", questions.get(0).getQuestionText());
data.put("options", questions.get(0).getOptions());
System.out.println("✅ === 试卷生成成功 ===");
return new ApiResponse(true, "试卷生成成功", data);
} catch (Exception e) {
System.err.println("💥 生成试卷时发生严重异常: " + e.getMessage());
e.printStackTrace();
return new ApiResponse(false, "系统错误: " + e.getMessage(), null);
}
}
// 获取题目
public ApiResponse getQuestion(String sessionId, int questionIndex) {
String username = validateSession(sessionId);
if (username == null) {
return new ApiResponse(false, "会话无效或已过期", null);
}
Exam exam = userExams.get(sessionId);
if (exam == null) {
return new ApiResponse(false, "没有进行中的考试", null);
}
List<Question> questions = exam.getQuestions();
if (questionIndex < 0 || questionIndex >= questions.size()) {
return new ApiResponse(false, "无效的题目索引", null);
}
Question question = questions.get(questionIndex);
Map<String, Object> data = new HashMap<>();
data.put("examId", exam.getExamId());
data.put("totalQuestions", questions.size());
data.put("currentQuestion", questionIndex);
data.put("question", question.getQuestionText());
data.put("options", question.getOptions());
data.put("userAnswer", exam.getUserAnswers().get(questionIndex));
return new ApiResponse(true, "获取题目成功", data);
}
// 提交答案
public ApiResponse submitAnswer(String sessionId, int questionIndex, int answerIndex) {
String username = validateSession(sessionId);
if (username == null) {
return new ApiResponse(false, "会话无效或已过期", null);
}
Exam exam = userExams.get(sessionId);
if (exam == null) {
return new ApiResponse(false, "没有进行中的考试", null);
}
exam.setAnswer(questionIndex, answerIndex);
Map<String, Object> data = new HashMap<>();
data.put("currentQuestion", questionIndex);
return new ApiResponse(true, "答案提交成功", data);
}
// 完成考试
public ApiResponse finishExam(String sessionId) {
String username = validateSession(sessionId);
if (username == null) {
return new ApiResponse(false, "会话无效或已过期", null);
}
Exam exam = userExams.get(sessionId);
if (exam == null) {
return new ApiResponse(false, "没有进行中的考试", null);
}
double score = exam.calculateScore();
// 保存考试记录
saveExamResult(username, exam, score);
// 移除当前考试
userExams.remove(sessionId);
Map<String, Object> data = new HashMap<>();
data.put("score", score);
data.put("totalQuestions", exam.getQuestions().size());
return new ApiResponse(true, "考试完成", data);
}
// 保存考试结果
private void saveExamResult(String username, Exam exam, double score) {
String userDir = baseDirectory + File.separator + username;
File dir = new File(userDir);
if (!dir.exists()) {
dir.mkdir();
}
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
String filename = userDir + File.separator + timestamp + "_score_" + String.format("%.1f", score) + ".txt";
try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
writer.println("考试ID: " + exam.getExamId());
writer.println("考试时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exam.getStartTime()));
writer.println("得分: " + String.format("%.1f", score) + "分");
writer.println();
List<Question> questions = exam.getQuestions();
List<Integer> userAnswers = exam.getUserAnswers();
for (int i = 0; i < questions.size(); i++) {
Question q = questions.get(i);
writer.println((i + 1) + ". " + q.getQuestionText());
List<String> options = q.getOptions();
for (int j = 0; j < options.size(); j++) {
String prefix = (j == q.getCorrectAnswerIndex()) ? "[正确答案] " :
(j == userAnswers.get(i)) ? "[您的答案] " : "";
writer.println(" " + (char)('A' + j) + ". " + prefix + options.get(j));
}
writer.println();
}
} catch (IOException e) {
System.out.println("保存考试结果失败: " + e.getMessage());
}
}
// 获取对应的题目生成器
private QuestionGenerator getQuestionGenerator(String userType) {
System.out.println("🎯 为类型 '" + userType + "' 选择题目生成器");
switch (userType) {
case "小学":
System.out.println("使用修复后的小学题目生成器 - 支持1-5个操作数");
return new PrimarySchoolGenerator();
case "初中":
System.out.println("使用修复后的初中题目生成器");
return new JuniorHighGenerator();
case "高中":
System.out.println("使用修复后的高中题目生成器");
return new SeniorHighGenerator();
default:
System.out.println("未知用户类型,使用稳定生成器");
return new StableQuestionGenerator();
}
}
// 退出登录
// 在logout方法中添加更详细的日志
public ApiResponse logout(String sessionId) {
System.out.println("=== 退出登录处理 ===");
System.out.println("请求的sessionId: " + sessionId);
System.out.println("当前活跃会话: " + userSessions.keySet());
String username = userSessions.remove(sessionId);
userExams.remove(sessionId);
System.out.println("移除的用户名: " + username);
System.out.println("移除后活跃会话: " + userSessions.keySet());
// 即使sessionId无效也返回成功确保前端可以继续流程
if (username != null) {
System.out.println("退出登录成功 - 用户: " + username);
return new ApiResponse(true, "退出成功", null);
} else {
System.out.println("退出登录 - sessionId无效但返回成功");
return new ApiResponse(true, "退出成功", null);
}
}
// 启动HTTP服务器
public void startServer(int port) throws IOException {
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
// 注册端点
server.createContext("/api/register", new RegisterHandler());
server.createContext("/api/login", new LoginHandler());
server.createContext("/api/change-password", new ChangePasswordHandler());
server.createContext("/api/generate-exam", new GenerateExamHandler());
server.createContext("/api/get-question", new GetQuestionHandler());
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);
}
// 内部HTTP处理器类
private abstract class BaseHandler implements HttpHandler {
protected Map<String, String> parseFormData(String formData) {
Map<String, String> params = new HashMap<>();
if (formData != null && !formData.isEmpty()) {
String[] pairs = formData.split("&");
for (String pair : pairs) {
String[] keyValue = pair.split("=");
if (keyValue.length == 2) {
try {
params.put(keyValue[0], java.net.URLDecoder.decode(keyValue[1], "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
return params;
}
protected void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException {
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8");
exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type");
exchange.sendResponseHeaders(statusCode, response.getBytes("UTF-8").length);
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes("UTF-8"));
os.close();
}
protected String toJson(ApiResponse response) {
// 简化的JSON序列化实际应用中可以使用Jackson等库
return "{\"success\":" + response.isSuccess() +
",\"message\":\"" + response.getMessage() + "\"" +
",\"data\":" + objectToJson(response.getData()) + "}";
}
private String objectToJson(Object obj) {
if (obj == null) return "null";
if (obj instanceof Map) {
Map<?, ?> map = (Map<?, ?>) obj;
StringBuilder sb = new StringBuilder("{");
boolean first = true;
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (!first) sb.append(",");
sb.append("\"").append(entry.getKey()).append("\":");
sb.append(objectToJson(entry.getValue()));
first = false;
}
sb.append("}");
return sb.toString();
} else if (obj instanceof List) {
List<?> list = (List<?>) obj;
StringBuilder sb = new StringBuilder("[");
boolean first = true;
for (Object item : list) {
if (!first) sb.append(",");
sb.append(objectToJson(item));
first = false;
}
sb.append("]");
return sb.toString();
} else if (obj instanceof String) {
return "\"" + obj.toString().replace("\"", "\\\"") + "\"";
} else {
return obj.toString();
}
}
}
private class RegisterHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String email = params.get("email");
String registrationCode = params.get("registrationCode");
String username = params.get("username");
String password = params.get("password");
String confirmPassword = params.get("confirmPassword");
String userType = params.get("userType");
ApiResponse response = register(email, registrationCode, username, password, confirmPassword, userType);
sendResponse(exchange, 200, toJson(response));
}
}
private class LoginHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String username = params.get("username");
String password = params.get("password");
ApiResponse response = login(username, password);
sendResponse(exchange, 200, toJson(response));
}
}
//处理器都正确实现
private class GenerateExamHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String sessionId = params.get("sessionId");
String userType = params.get("userType");
int questionCount = Integer.parseInt(params.get("questionCount"));
ApiResponse response = generateExam(sessionId, userType, questionCount);
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
ApiResponse errorResponse = new ApiResponse(false, "生成试卷失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
private class GetQuestionHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String sessionId = params.get("sessionId");
int questionIndex = Integer.parseInt(params.get("questionIndex"));
ApiResponse response = getQuestion(sessionId, questionIndex);
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
ApiResponse errorResponse = new ApiResponse(false, "获取题目失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
private class SubmitAnswerHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String sessionId = params.get("sessionId");
int questionIndex = Integer.parseInt(params.get("questionIndex"));
int answerIndex = Integer.parseInt(params.get("answerIndex"));
ApiResponse response = submitAnswer(sessionId, questionIndex, answerIndex);
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
ApiResponse errorResponse = new ApiResponse(false, "提交答案失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
private class FinishExamHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String sessionId = params.get("sessionId");
ApiResponse response = finishExam(sessionId);
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
ApiResponse errorResponse = new ApiResponse(false, "完成考试失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
private class ChangePasswordHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String sessionId = params.get("sessionId");
String oldPassword = params.get("oldPassword");
String newPassword = params.get("newPassword");
String confirmPassword = params.get("confirmPassword");
ApiResponse response = changePassword(sessionId, oldPassword, newPassword, confirmPassword);
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
ApiResponse errorResponse = new ApiResponse(false, "修改密码失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
private class LogoutHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
Map<String, String> params = parseFormData(requestBody);
String sessionId = params.get("sessionId");
ApiResponse response = logout(sessionId);
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
ApiResponse errorResponse = new ApiResponse(false, "退出登录失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
// 发送注册码的处理器
private class SendRegistrationCodeHandler extends BaseHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
System.out.println("处理发送注册码请求");
if ("OPTIONS".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 200, "");
return;
}
if (!"POST".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}");
return;
}
try {
String requestBody = new String(exchange.getRequestBody().readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
System.out.println("请求体: " + requestBody);
Map<String, String> params = parseFormData(requestBody);
String email = params.get("email");
System.out.println("解析到的邮箱: " + email);
ApiResponse response = sendRegistrationCode(email);
System.out.println("发送响应: " + toJson(response));
sendResponse(exchange, 200, toJson(response));
} catch (Exception e) {
System.err.println("发送注册码时发生错误: " + e.getMessage());
e.printStackTrace();
ApiResponse errorResponse = new ApiResponse(false, "获取验证码失败: " + e.getMessage(), null);
sendResponse(exchange, 500, toJson(errorResponse));
}
}
}
public static void main(String[] args) {
try {
Main system = new Main();
system.startServer(8080); // 启动在8080端口
} catch (IOException e) {
System.err.println("启动服务器失败: " + e.getMessage());
}
}
}

@ -1,221 +0,0 @@
package com.mathlearn.generator;
import com.mathlearn.model.exam.Question;
import java.util.*;
public class JuniorHighGenerator implements QuestionGenerator {
private Random random = new Random();
@Override
public Question generateQuestion() {
int type = random.nextInt(5); // 0-4: 五种题型
String questionText = "";
double correctAnswerValue = 0;
boolean isIntegerAnswer = true;
switch (type) {
case 0: // 基本四则运算(考虑优先级)
questionText = generateArithmeticQuestion();
correctAnswerValue = evaluateExpression(questionText.replace(" = ?", ""));
isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue);
break;
case 1: // 平方运算(支持负数)
int base = random.nextInt(25) - 12; // -12到12的平方
questionText = "(" + base + ")² = ?";
correctAnswerValue = base * base;
break;
case 2: // 平方根运算(完全平方数)
int square = getPerfectSquare();
int root = (int)Math.sqrt(square);
questionText = "√" + square + " = ?";
correctAnswerValue = root;
break;
case 3: // 次方运算(合理大小)
int baseNum = random.nextInt(8) + 2; // 2-9
int exponent = random.nextInt(4) + 2; // 2-5次方
questionText = baseNum + "^" + exponent + " = ?";
correctAnswerValue = Math.pow(baseNum, exponent);
break;
case 4: // 带负数的简单运算
int a = random.nextInt(20) - 10; // -10到10
int b = random.nextInt(20) - 10;
String[] ops = {"+", "-", "×"};
String op = ops[random.nextInt(ops.length)];
questionText = "(" + a + ") " + op + " (" + b + ") = ?";
correctAnswerValue = calculateSimpleOperation(a, b, op);
isIntegerAnswer = true;
break;
}
List<String> options = generateOptions(correctAnswerValue, isIntegerAnswer);
String correctAnswerStr = isIntegerAnswer ?
String.valueOf((int)correctAnswerValue) :
String.format("%.2f", correctAnswerValue);
int correctIndex = options.indexOf(correctAnswerStr);
return new Question(questionText, options, correctIndex);
}
// 生成考虑优先级的算术题目
private String generateArithmeticQuestion() {
int operandCount = random.nextInt(3) + 2; // 2-4个操作数
StringBuilder question = new StringBuilder();
List<String> 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(" ");
}
// 生成合适的操作数
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(" = ?");
return question.toString();
}
// 生成能整除的数(用于除法运算)
private int generateDivisibleNumber() {
int[] smallNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
return smallNumbers[random.nextInt(smallNumbers.length)];
}
// 计算简单运算(支持负数)
private int calculateSimpleOperation(int a, int b, String op) {
switch (op) {
case "+": return a + b;
case "-": return a - b;
case "×": return a * b;
default: return a + b;
}
}
// 计算表达式(考虑运算优先级)- 使用自定义解析器避免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, 169, 196, 225, 256, 289, 324, 361, 400};
return perfectSquares[random.nextInt(perfectSquares.length)];
}
private List<String> generateOptions(double correctAnswer, boolean isInteger) {
List<String> options = new ArrayList<>();
String correctStr = isInteger ?
String.valueOf((int)correctAnswer) :
String.format("%.2f", correctAnswer);
options.add(correctStr);
Set<String> used = new HashSet<>();
used.add(correctStr);
// 生成3个错误选项
while (options.size() < 4) {
double wrongValue;
String wrongStr;
do {
// 根据正确答案的大小调整变化范围
double range = Math.max(5, Math.abs(correctAnswer) * 0.3);
double variation = (random.nextDouble() * range) + 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);
}
} while (used.contains(wrongStr) || Double.isNaN(wrongValue) || Double.isInfinite(wrongValue));
options.add(wrongStr);
used.add(wrongStr);
}
Collections.shuffle(options);
return options;
}
}

@ -1,219 +0,0 @@
package com.mathlearn.generator;
import com.mathlearn.model.exam.Question;
import java.util.*;
public class PrimarySchoolGenerator implements QuestionGenerator {
private Random random = new Random();
private String[] operators = {"+", "-", "×", "÷"};
private int maxAttempts = 100; // 最大尝试次数,避免无限循环
@Override
public Question generateQuestion() {
int attempts = 0;
while (attempts < maxAttempts) {
attempts++;
try {
// 生成2-3个操作数避免太复杂
int operandCount = random.nextInt(2) + 2; // 2-3个操作数
StringBuilder question = new StringBuilder();
List<Integer> operands = new ArrayList<>();
List<String> usedOperators = new ArrayList<>();
// 生成操作数和运算符,确保表达式合法
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
String op = operators[random.nextInt(operators.length)];
question.append(" ").append(op).append(" ");
usedOperators.add(op);
}
// 生成合适的操作数范围
int num = generateSuitableNumber(i, usedOperators, operands);
question.append(num);
operands.add(num);
}
question.append(" = ?");
// 验证表达式合法性
if (!isExpressionValid(operands, usedOperators)) {
continue; // 重新生成
}
// 计算正确答案
int correctAnswer = calculateAnswerWithPriority(operands, usedOperators);
// 确保结果不为负数
if (correctAnswer < 0) {
continue; // 重新生成
}
// 生成选项并获取正确答案索引
List<String> options = generateOptions(correctAnswer);
int correctIndex = options.indexOf(String.valueOf(correctAnswer));
System.out.println("✅ 成功生成小学题目: " + question.toString() + " = " + correctAnswer);
return new Question(question.toString(), options, correctIndex);
} catch (Exception e) {
System.err.println("生成小学题目失败,尝试次数: " + attempts + ", 错误: " + e.getMessage());
// 继续尝试
}
}
// 如果多次尝试都失败,返回一个简单的默认题目
System.out.println("⚠️ 使用默认小学题目");
return new Question("2 + 3 = ?", Arrays.asList("5", "6", "4", "7"), 0);
}
// 生成合适的数字
private int generateSuitableNumber(int index, List<String> operators, List<Integer> operands) {
if (index == 0) {
// 第一个操作数
return random.nextInt(50) + 1; // 1-50
}
// 根据前一个运算符决定当前操作数的范围
String lastOperator = operators.get(operators.size() - 1);
switch (lastOperator) {
case "-":
// 减法:第二个操作数不能太大,避免负数
int previous = operands.get(operands.size() - 1);
return random.nextInt(Math.min(previous, 20)) + 1;
case "÷":
// 除法:除数要小,且要能整除
previous = operands.get(operands.size() - 1);
List<Integer> divisors = findDivisors(previous);
if (!divisors.isEmpty()) {
return divisors.get(random.nextInt(divisors.size()));
}
return random.nextInt(10) + 1; // 备选
case "×":
// 乘法:避免结果太大
return random.nextInt(5) + 1; // 1-5
default:
return random.nextInt(50) + 1; // 1-50
}
}
// 找到能整除的数
private List<Integer> findDivisors(int number) {
List<Integer> divisors = new ArrayList<>();
for (int i = 1; i <= Math.min(number, 10); i++) {
if (number % i == 0) {
divisors.add(i);
}
}
return divisors;
}
// 验证表达式是否合法
private boolean isExpressionValid(List<Integer> operands, List<String> operators) {
try {
// 计算中间结果,验证每一步都合法
int result = operands.get(0);
for (int i = 0; i < operators.size(); i++) {
String op = operators.get(i);
int next = operands.get(i + 1);
switch (op) {
case "-":
if (result < next) return false; // 减法结果不能为负
break;
case "÷":
if (next == 0 || result % next != 0) return false; // 除数不能为0且要能整除
break;
}
result = applyOperation(result, op, next);
if (result < 0) return false; // 最终结果不能为负
}
return true;
} catch (Exception e) {
return false;
}
}
// 考虑运算优先级的计算
private int calculateAnswerWithPriority(List<Integer> operands, List<String> operators) {
if (operands.size() == 1) return operands.get(0);
// 先处理所有乘除法
List<Object> processed = new ArrayList<>();
processed.add(operands.get(0));
for (int i = 0; i < operators.size(); i++) {
String op = operators.get(i);
int nextOperand = operands.get(i + 1);
if (op.equals("×") || op.equals("÷")) {
// 执行乘除运算
int lastIndex = processed.size() - 1;
int lastValue = (Integer) processed.get(lastIndex);
int result = applyOperation(lastValue, op, nextOperand);
processed.set(lastIndex, result);
} else {
// 加减法先保留
processed.add(op);
processed.add(nextOperand);
}
}
// 再处理加减法
int result = (Integer) processed.get(0);
for (int i = 1; i < processed.size(); i += 2) {
String op = (String) processed.get(i);
int nextOperand = (Integer) processed.get(i + 1);
result = applyOperation(result, op, nextOperand);
}
return result;
}
// 执行单个运算
private int applyOperation(int a, String operator, int b) {
switch (operator) {
case "+": return a + b;
case "-": return a - b; // 前面已经验证不会为负
case "×": return a * b;
case "÷": return a / b; // 前面已经验证能整除
default: return a;
}
}
private List<String> generateOptions(int correctAnswer) {
List<String> options = new ArrayList<>();
options.add(String.valueOf(correctAnswer));
Set<Integer> used = new HashSet<>();
used.add(correctAnswer);
// 生成3个错误选项
while (options.size() < 4) {
int variation = random.nextInt(10) + 1;
boolean add = random.nextBoolean();
int wrongAnswer = add ? correctAnswer + variation : Math.max(0, correctAnswer - variation);
if (!used.contains(wrongAnswer) && wrongAnswer != correctAnswer) {
options.add(String.valueOf(wrongAnswer));
used.add(wrongAnswer);
}
// 防止无限循环
if (options.size() < 4 && used.size() > 10) {
// 强制添加一些选项
for (int i = 1; i <= 3; i++) {
int forcedOption = correctAnswer + i * 2;
if (!used.contains(forcedOption)) {
options.add(String.valueOf(forcedOption));
used.add(forcedOption);
if (options.size() >= 4) break;
}
}
}
}
Collections.shuffle(options);
return options;
}
}

@ -1,8 +0,0 @@
package com.mathlearn.generator;
import com.mathlearn.model.exam.Question;
public interface QuestionGenerator {
Question generateQuestion();
}

@ -1,425 +0,0 @@
package com.mathlearn.generator;
import com.mathlearn.model.exam.Question;
import java.util.*;
public class SeniorHighGenerator implements QuestionGenerator {
private Random random = new Random();
@Override
public Question generateQuestion() {
int type = random.nextInt(6); // 六种题型
String questionText = "";
double correctAnswerValue = 0;
boolean isIntegerAnswer = true;
switch (type) {
case 0: // 三角函数(特殊角,包括负角)
String[] trigFunctions = {"sin", "cos", "tan"};
String func = trigFunctions[random.nextInt(trigFunctions.length)];
int angle = getSpecialAngle();
questionText = func + "(" + angle + "°) = ?";
correctAnswerValue = calculateTrigValue(func, angle);
isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue);
break;
case 1: // 平方根(包括非完全平方数的近似值)
if (random.nextBoolean()) {
// 完全平方数
int square = getPerfectSquare();
questionText = "√" + square + " = ?";
correctAnswerValue = Math.sqrt(square);
} else {
// 非完全平方数的近似值
int num = getNonPerfectSquare();
questionText = "√" + num + " ≈ ?";
correctAnswerValue = Math.sqrt(num);
isIntegerAnswer = false;
}
break;
case 2: // 对数运算
questionText = generateLogQuestion();
correctAnswerValue = evaluateLogQuestion(questionText);
isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue);
break;
case 3: // 复合表达式(考虑优先级)
ExpressionResult exprResult = generateCompositeExpression();
questionText = exprResult.expression;
correctAnswerValue = exprResult.value;
isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue);
break;
case 4: // 二次方程
int root = random.nextInt(15) - 7; // -7到7的根
int a = 1;
int b = -2 * root;
int c = root * root;
questionText = String.format("方程 %dx² %s %dx %s %d = 0 的一个根是?",
a, b >= 0 ? "+" : "", b, c >= 0 ? "+" : "", c);
correctAnswerValue = root;
break;
case 5: // 带指数的复合运算
questionText = generateExponentialExpression();
correctAnswerValue = evaluateExponentialExpression(questionText.replace(" = ?", ""));
isIntegerAnswer = (correctAnswerValue == (int)correctAnswerValue);
break;
}
List<String> options = generateOptions(correctAnswerValue, isIntegerAnswer);
String correctAnswerStr = isIntegerAnswer ?
String.valueOf((int)correctAnswerValue) :
String.format("%.2f", correctAnswerValue);
int correctIndex = options.indexOf(correctAnswerStr);
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 generateCompositeExpression() {
// 使用预定义的简单表达式模板,确保可计算
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", "先加后乘"}
};
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且能整除
a = random.nextInt(10) + 1;
b = random.nextInt(10) + 1;
c = random.nextInt(10) + 1;
// 调整数字确保除法有效
if (pattern.startsWith("%d ÷")) {
// 第一个操作数是除法确保b能整除a
a = b * (random.nextInt(5) + 1); // a是b的倍数
} else if (pattern.contains("÷ %d")) {
// 其他位置的除法确保除数不为0
b = random.nextInt(9) + 1; // 1-9
}
} else if (pattern.contains("²")) {
// 平方模板
a = random.nextInt(10) + 1; // 1-10
b = random.nextInt(20) + 1; // 1-20
result = a * a + (pattern.contains("+") ? b : -b);
} else if (pattern.contains("(")) {
// 括号模板
a = random.nextInt(10) + 1;
b = random.nextInt(10) + 1;
c = random.nextInt(10) + 1;
result = pattern.contains("× (") ? a * (b + c) : (a + b) * c;
} else {
// 基本四则运算
a = random.nextInt(10) + 1;
b = random.nextInt(10) + 1;
c = random.nextInt(10) + 1;
// 根据运算符计算结果
if (pattern.contains("+ %d ×")) {
result = a + b * c; // a + b × c
} else if (pattern.contains("× %d +")) {
result = a * b + c; // a × b + c
} else if (pattern.contains("- %d ×")) {
result = a - b * c; // a - b × c
} else if (pattern.contains("× %d -")) {
result = a * b - c; // a × b - c
} else if (pattern.contains("+ %d ÷")) {
result = a + (double)b / c; // a + b ÷ c
} else if (pattern.contains("÷ %d +")) {
result = (double)a / b + c; // a ÷ b + c
}
}
// 如果还没有计算结果,使用安全的表达式计算
if (result == 0) {
result = safeEvaluateExpression(pattern, a, b, c);
}
String expression = String.format(pattern, a, b, c) + " = ?";
System.out.println("生成表达式: " + expression + " [规则: " + description + "] = " + result);
return new ExpressionResult(expression, result);
}
// 安全的表达式计算
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")) {
return a * a + b;
} else if (pattern.equals("%d² - %d")) {
return a * a - b;
} 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 getSpecialAngle() {
int[] angles = {-360, -270, -180, -135, -120, -90, -60, -45, -30, 0,
30, 45, 60, 90, 120, 135, 180, 270, 360};
return angles[random.nextInt(angles.length)];
}
// 获取非完全平方数
private int getNonPerfectSquare() {
int[] nonSquares = {2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20};
return nonSquares[random.nextInt(nonSquares.length)];
}
// 生成对数题目
private String generateLogQuestion() {
if (random.nextBoolean()) {
// 简单对数log₁₀
int value = (int)Math.pow(10, random.nextInt(4)); // 1, 10, 100, 1000
return "log₁₀" + value + " = ?";
} else {
// 以2为底的对数
int value = (int)Math.pow(2, random.nextInt(6) + 1); // 2,4,8,16,32,64
return "log₂" + value + " = ?";
}
}
// 计算对数题目
private double evaluateLogQuestion(String question) {
if (question.startsWith("log₁₀")) {
int value = Integer.parseInt(question.replace("log₁₀", "").replace(" = ?", ""));
return Math.log10(value);
} else if (question.startsWith("log₂")) {
int value = Integer.parseInt(question.replace("log₂", "").replace(" = ?", ""));
return Math.log(value) / Math.log(2);
}
return 0;
}
// 生成指数表达式
private String generateExponentialExpression() {
int base = random.nextInt(5) + 2; // 2-6
int exponent = random.nextInt(4) + 2; // 2-5
return base + "^" + exponent + " = ?";
}
// 计算指数表达式
private double evaluateExponentialExpression(String expr) {
String cleanExpr = expr.replace(" = ?", "");
String[] parts = cleanExpr.split("\\^");
int base = Integer.parseInt(parts[0]);
int exponent = Integer.parseInt(parts[1]);
return Math.pow(base, exponent);
}
private double calculateTrigValue(String function, int angle) {
// 规范化角度到0-360度
angle = angle % 360;
if (angle < 0) angle += 360;
// 特殊角的精确值
switch (angle) {
case 0:
if (function.equals("sin")) return 0;
if (function.equals("cos")) return 1;
if (function.equals("tan")) return 0;
break;
case 30:
if (function.equals("sin")) return 0.5;
if (function.equals("cos")) return Math.sqrt(3)/2;
if (function.equals("tan")) return 1/Math.sqrt(3);
break;
case 45:
double sqrt2 = Math.sqrt(2);
if (function.equals("sin")) return sqrt2/2;
if (function.equals("cos")) return sqrt2/2;
if (function.equals("tan")) return 1;
break;
case 60:
if (function.equals("sin")) return Math.sqrt(3)/2;
if (function.equals("cos")) return 0.5;
if (function.equals("tan")) return Math.sqrt(3);
break;
case 90:
if (function.equals("sin")) return 1;
if (function.equals("cos")) return 0;
if (function.equals("tan")) return Double.POSITIVE_INFINITY;
break;
case 120:
if (function.equals("sin")) return Math.sqrt(3)/2;
if (function.equals("cos")) return -0.5;
if (function.equals("tan")) return -Math.sqrt(3);
break;
case 135:
double sqrt22 = Math.sqrt(2)/2;
if (function.equals("sin")) return sqrt22;
if (function.equals("cos")) return -sqrt22;
if (function.equals("tan")) return -1;
break;
case 150:
if (function.equals("sin")) return 0.5;
if (function.equals("cos")) return -Math.sqrt(3)/2;
if (function.equals("tan")) return -1/Math.sqrt(3);
break;
case 180:
if (function.equals("sin")) return 0;
if (function.equals("cos")) return -1;
if (function.equals("tan")) return 0;
break;
case 270:
if (function.equals("sin")) return -1;
if (function.equals("cos")) return 0;
if (function.equals("tan")) return Double.NEGATIVE_INFINITY;
break;
}
// 对于非特殊角,使用近似计算
double rad = Math.toRadians(angle);
switch (function) {
case "sin":
return Math.round(Math.sin(rad) * 100) / 100.0;
case "cos":
return Math.round(Math.cos(rad) * 100) / 100.0;
case "tan":
if (angle % 180 == 90) {
return angle % 360 == 90 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
}
double result = Math.tan(rad);
return Math.round(result * 100) / 100.0;
default:
return 0;
}
}
private int getPerfectSquare() {
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)];
}
private List<String> generateOptions(double correctAnswer, boolean isInteger) {
List<String> options = new ArrayList<>();
String correctStr;
if (Double.isInfinite(correctAnswer)) {
correctStr = correctAnswer > 0 ? "∞" : "-∞";
} else if (Double.isNaN(correctAnswer)) {
correctStr = "无解";
} else {
correctStr = isInteger ?
String.valueOf((int)correctAnswer) :
String.format("%.2f", correctAnswer);
}
options.add(correctStr);
Set<String> used = new HashSet<>();
used.add(correctStr);
// 生成3个错误选项
int attempts = 0;
while (options.size() < 4 && attempts < 50) {
attempts++;
double wrongValue;
String wrongStr;
// 根据正确答案调整变化范围
double baseRange;
if (Double.isInfinite(correctAnswer) || Double.isNaN(correctAnswer)) {
baseRange = 5;
} else {
baseRange = Math.max(2, Math.abs(correctAnswer) * 0.3);
}
double variation = (random.nextDouble() * baseRange) + 1;
boolean positive = random.nextBoolean();
if (Double.isInfinite(correctAnswer)) {
wrongValue = random.nextDouble() * 10 - 5; // -5到5的随机数
} else if (Double.isNaN(correctAnswer)) {
wrongValue = random.nextDouble() * 10; // 0到10的随机数
} else {
wrongValue = correctAnswer + (positive ? variation : -variation);
}
if (Double.isInfinite(wrongValue)) {
wrongStr = wrongValue > 0 ? "∞" : "-∞";
} else if (Double.isNaN(wrongValue)) {
wrongStr = "无解";
} else if (isInteger) {
wrongValue = Math.round(wrongValue);
wrongStr = String.valueOf((int)wrongValue);
} else {
wrongValue = Math.round(wrongValue * 100) / 100.0;
wrongStr = String.format("%.2f", wrongValue);
}
if (!used.contains(wrongStr)) {
options.add(wrongStr);
used.add(wrongStr);
}
}
// 如果选项不够,添加一些固定选项
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 (!used.contains(extraOption)) {
options.add(extraOption);
used.add(extraOption);
}
}
Collections.shuffle(options);
return options;
}
}

@ -1,107 +0,0 @@
package com.mathlearn.generator;
//稳定生成器
import com.mathlearn.model.exam.Question;
import java.util.*;
public class StableQuestionGenerator implements QuestionGenerator {
private Random random = new Random();
private int questionCounter = 0;
@Override
public Question generateQuestion() {
questionCounter++;
System.out.println(" 🔧 生成第 " + questionCounter + " 道题目...");
try {
// 极度简化的题目生成,确保不会卡住
int a = random.nextInt(20) + 1;
int b = random.nextInt(20) + 1;
// 随机选择运算符
String[] operators = {"+", "-", "×"};
String operator = operators[random.nextInt(operators.length)];
String questionText;
int correctAnswer;
switch (operator) {
case "+":
questionText = a + " + " + b + " = ?";
correctAnswer = a + b;
break;
case "-":
// 确保减法结果不为负数
int larger = Math.max(a, b);
int smaller = Math.min(a, b);
questionText = larger + " - " + smaller + " = ?";
correctAnswer = larger - smaller;
break;
case "×":
// 简化乘法,避免过大数字
a = random.nextInt(10) + 1;
b = random.nextInt(10) + 1;
questionText = a + " × " + b + " = ?";
correctAnswer = a * b;
break;
default:
questionText = a + " + " + b + " = ?";
correctAnswer = a + b;
}
// 生成稳定的选项
List<String> options = generateStableOptions(correctAnswer);
System.out.println(" ✅ 题目生成成功: " + questionText);
return new Question(questionText, options, 0); // 第一个选项是正确答案
} catch (Exception e) {
System.err.println(" 💥 题目生成过程中发生异常: " + e.getMessage());
// 返回一个默认题目,确保不卡住
return new Question("1 + 1 = ?", Arrays.asList("2", "3", "4", "5"), 0);
}
}
private List<String> generateStableOptions(int correctAnswer) {
List<String> options = new ArrayList<>();
options.add(String.valueOf(correctAnswer));
// 生成3个稳定的错误选项
Set<Integer> used = new HashSet<>();
used.add(correctAnswer);
int[] variations = {1, 2, 3, 5, 7, 10}; // 固定的变化量
for (int i = 0; i < 3 && options.size() < 4; i++) {
int variation = variations[i % variations.length];
boolean addVariation = random.nextBoolean();
int wrongAnswer = addVariation ? correctAnswer + variation : correctAnswer - variation;
// 确保不为负数且不重复
if (wrongAnswer > 0 && !used.contains(wrongAnswer)) {
options.add(String.valueOf(wrongAnswer));
used.add(wrongAnswer);
} else {
// 如果生成失败,使用备选方案
wrongAnswer = correctAnswer + (i + 1) * 2;
if (!used.contains(wrongAnswer)) {
options.add(String.valueOf(wrongAnswer));
used.add(wrongAnswer);
}
}
}
// 如果选项还不够,用固定值补全
while (options.size() < 4) {
int filler = correctAnswer + options.size() * 5 + 1;
if (!used.contains(filler)) {
options.add(String.valueOf(filler));
used.add(filler);
}
}
Collections.shuffle(options);
return options;
}
}

@ -1,17 +0,0 @@
package com.mathlearn.model.api;
public class ApiResponse {
private boolean success;
private String message;
private Object data;
public ApiResponse(boolean success, String message, Object data) {
this.success = success;
this.message = message;
this.data = data;
}
public boolean isSuccess() { return success; }
public String getMessage() { return message; }
public Object getData() { return data; }
}

@ -1,46 +0,0 @@
package com.mathlearn.model.exam;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Exam {
private List<Question> questions;
private List<Integer> userAnswers;
private Date startTime;
private String examId;
public Exam(List<Question> questions) {
this.questions = questions;
this.userAnswers = new ArrayList<>();
this.startTime = new Date();
this.examId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
// 初始化用户答案列表
for (int i = 0; i < questions.size(); i++) {
userAnswers.add(-1); // -1表示未作答
}
}
public List<Question> getQuestions() { return questions; }
public List<Integer> getUserAnswers() { return userAnswers; }
public Date getStartTime() { return startTime; }
public String getExamId() { return examId; }
public void setAnswer(int questionIndex, int answerIndex) {
if (questionIndex >= 0 && questionIndex < userAnswers.size()) {
userAnswers.set(questionIndex, answerIndex);
}
}
public double calculateScore() {
int correctCount = 0;
for (int i = 0; i < questions.size(); i++) {
if (userAnswers.get(i) == questions.get(i).getCorrectAnswerIndex()) {
correctCount++;
}
}
return (double) correctCount / questions.size() * 100;
}
}

@ -1,19 +0,0 @@
package com.mathlearn.model.exam;
import java.util.List;
public class Question {
private String questionText;
private List<String> options;
private int correctAnswerIndex;
public Question(String questionText, List<String> options, int correctAnswerIndex) {
this.questionText = questionText;
this.options = options;
this.correctAnswerIndex = correctAnswerIndex;
}
public String getQuestionText() { return questionText; }
public List<String> getOptions() { return options; }
public int getCorrectAnswerIndex() { return correctAnswerIndex; }
}

@ -1,49 +0,0 @@
package com.mathlearn.model.user;
// 用户账户类
public class UserAccount {
private String username;
private String password;
private String userType;
private String email; // 添加邮箱字段
private String registrationCode;
private boolean registered;
public UserAccount(String username, String password, String userType) {
this.username = username;
this.password = password;
this.userType = userType;
this.registered = true;
}
public UserAccount(String username, String password, String userType, String email) {
this.username = username;
this.password = password;
this.userType = userType;
this.email = email;
this.registered = true;
}
public UserAccount(String email, String registrationCode) {
this.email = email;
this.registrationCode = registrationCode;
this.registered = false;
}
public void completeRegistration(String username, String password, String userType) {
this.username = username;
this.password = password;
this.userType = userType;
this.registered = true;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
public String getUserType() { return userType; }
public String getRegistrationCode() { return registrationCode; }
public boolean isRegistered() { return registered; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
Loading…
Cancel
Save