diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e288f29..49005d2 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,6 +6,7 @@ +<<<<<<< HEAD @@ -45,6 +46,14 @@ +======= + + + + + + +>>>>>>> develop +<<<<<<< HEAD { + "keyToString": { + "Maven.mathquiz [clean].executor": "Run", + "Maven.mathquiz [compile].executor": "Run", + "Maven.mathquiz [org.openjfx:javafx-maven-plugin:0.0.8:run].executor": "Run", + "Maven.mathquiz [package].executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "git-widget-placeholder": "develop", + "ignore.virus.scanning.warn.message": "true", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "C:/Users/lyq20/OneDrive/桌面/Finally/MathQuiz", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "vue.rearranger.settings.migration": "true" +>>>>>>> develop } -}]]> +} @@ -111,6 +140,7 @@ + diff --git a/src/main/java/com/student/mathquiz/MainApp.java b/src/main/java/com/student/mathquiz/MainApp.java index 5fd970f..4a08ea3 100644 --- a/src/main/java/com/student/mathquiz/MainApp.java +++ b/src/main/java/com/student/mathquiz/MainApp.java @@ -89,6 +89,7 @@ public class MainApp extends Application { } } +<<<<<<< HEAD // ... (所有其他方法保持不变) public void handleLoginSuccess(String email) { this.currentUserEmail = email; @@ -106,6 +107,18 @@ public class MainApp extends Application { public void showMainMenuView() { switchScene("MainMenuView.fxml"); } +======= + // ★★★ 修改这个方法的参数类型,从 String 改为 User ★★★ + public void handleLoginSuccess(com.student.mathquiz.model.User user) { + // ★★★ 从 User 对象中,准确地获取并保存 email!★★★ + this.currentUserEmail = user.getEmail(); + showMainMenuView(); + } + + public void showLoginView() { switchScene("LoginView.fxml"); } + public void showRegisterView() { switchScene("RegisterView.fxml"); } + public void showMainMenuView() { switchScene("MainMenuView.fxml"); } +>>>>>>> develop // 在 MainApp.java 中 public void showQuizView(String level, int count) { diff --git a/src/main/java/com/student/mathquiz/question/HighQuestionGenerator.java b/src/main/java/com/student/mathquiz/question/HighQuestionGenerator.java index 2c44fc3..e1d7dd6 100644 --- a/src/main/java/com/student/mathquiz/question/HighQuestionGenerator.java +++ b/src/main/java/com/student/mathquiz/question/HighQuestionGenerator.java @@ -3,12 +3,22 @@ package com.student.mathquiz.question; import java.util.*; public class HighQuestionGenerator implements QuestionGenerator { +<<<<<<< HEAD private static final Random RANDOM = new Random(); private static final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"}; private static final Map TRIG_VALUES = new HashMap<>(); +======= +>>>>>>> develop + private static final Random RANDOM = new Random(); + private static final String[] FUNCTIONS = {"sin", "cos", "tan"}; + private static final Map TRIG_EXACT_VALUES = new HashMap<>(); + private final Set seenQuestions = new HashSet<>(); + + // 静态初始化三角函数精确值表(特殊角) static { +<<<<<<< HEAD TRIG_VALUES.put("sin30", "1/2"); TRIG_VALUES.put("sin45", "√2/2"); TRIG_VALUES.put("sin60", "√3/2"); @@ -18,33 +28,113 @@ public class HighQuestionGenerator implements QuestionGenerator { TRIG_VALUES.put("tan30", "√3/3"); TRIG_VALUES.put("tan45", "1"); TRIG_VALUES.put("tan60", "√3"); +======= + // 0° + TRIG_EXACT_VALUES.put("sin0", "0"); + TRIG_EXACT_VALUES.put("cos0", "1"); + TRIG_EXACT_VALUES.put("tan0", "0"); + + // 15° + TRIG_EXACT_VALUES.put("sin15", "(√6-√2)/4"); + TRIG_EXACT_VALUES.put("cos15", "(√6+√2)/4"); + TRIG_EXACT_VALUES.put("tan15", "2-√3"); + + // 30° + TRIG_EXACT_VALUES.put("sin30", "1/2"); + TRIG_EXACT_VALUES.put("cos30", "√3/2"); + TRIG_EXACT_VALUES.put("tan30", "√3/3"); + + // 45° + TRIG_EXACT_VALUES.put("sin45", "√2/2"); + TRIG_EXACT_VALUES.put("cos45", "√2/2"); + TRIG_EXACT_VALUES.put("tan45", "1"); + + // 60° + TRIG_EXACT_VALUES.put("sin60", "√3/2"); + TRIG_EXACT_VALUES.put("cos60", "1/2"); + TRIG_EXACT_VALUES.put("tan60", "√3"); + + // 75° + TRIG_EXACT_VALUES.put("sin75", "(√6+√2)/4"); + TRIG_EXACT_VALUES.put("cos75", "(√6-√2)/4"); + TRIG_EXACT_VALUES.put("tan75", "2+√3"); + + // 90° + TRIG_EXACT_VALUES.put("sin90", "1"); + TRIG_EXACT_VALUES.put("cos90", "0"); + TRIG_EXACT_VALUES.put("tan90", null); // 无定义 + + // 105° + TRIG_EXACT_VALUES.put("sin105", "(√6+√2)/4"); + TRIG_EXACT_VALUES.put("cos105", "-(√6-√2)/4"); + TRIG_EXACT_VALUES.put("tan105", "-2-√3"); + + // 120° + TRIG_EXACT_VALUES.put("sin120", "√3/2"); + TRIG_EXACT_VALUES.put("cos120", "-1/2"); + TRIG_EXACT_VALUES.put("tan120", "-√3"); + + // 135° + TRIG_EXACT_VALUES.put("sin135", "√2/2"); + TRIG_EXACT_VALUES.put("cos135", "-√2/2"); + TRIG_EXACT_VALUES.put("tan135", "-1"); + + // 150° + TRIG_EXACT_VALUES.put("sin150", "1/2"); + TRIG_EXACT_VALUES.put("cos150", "-√3/2"); + TRIG_EXACT_VALUES.put("tan150", "-√3/3"); + + // 165° + TRIG_EXACT_VALUES.put("sin165", "(√6-√2)/4"); + TRIG_EXACT_VALUES.put("cos165", "-(√6+√2)/4"); + TRIG_EXACT_VALUES.put("tan165", "-2+√3"); + + // 180° + TRIG_EXACT_VALUES.put("sin180", "0"); + TRIG_EXACT_VALUES.put("cos180", "-1"); + TRIG_EXACT_VALUES.put("tan180", "0"); + + // 其他角度可以继续补充... +>>>>>>> develop } @Override public Question generateQuestion() { - return generateTrigQuestion(); - } + while (true) { + String func = FUNCTIONS[RANDOM.nextInt(FUNCTIONS.length)]; + int angle = 15 * RANDOM.nextInt(201); // 0° ~ 3000°,步长15° + int normalizedAngle = angle % 360; + + String key = func + normalizedAngle; + String correctAnswer = TRIG_EXACT_VALUES.get(key); + + // 跳过无定义的角度(如 tan90°) + if (correctAnswer == null) continue; - private Question generateTrigQuestion() { - String func = TRIG_FUNCTIONS[RANDOM.nextInt(TRIG_FUNCTIONS.length)]; - String[] angles = {"30", "45", "60"}; - String angle = angles[RANDOM.nextInt(angles.length)]; + String content = func + "(" + angle + "°) = ?"; + if (seenQuestions.contains(content)) continue; + seenQuestions.add(content); - String content = func + "(" + angle + "°) = ?"; - String correctAnswer = TRIG_VALUES.get(func + angle); + List options = generateOptions(correctAnswer); + int correctIndex = shuffleOptions(options, correctAnswer); - List options = generateOptions(correctAnswer); - int correctIndex = shuffleOptions(options, correctAnswer); - return new Question(content, correctAnswer, options, correctIndex); + return new Question(content, correctAnswer, options, correctIndex); + } } + /** + * 生成3个干扰项 + 1个正确答案 + */ private List generateOptions(String correctAnswer) { Set options = new HashSet<>(); options.add(correctAnswer); - List allValues = new ArrayList<>(TRIG_VALUES.values()); + + List allValues = new ArrayList<>(TRIG_EXACT_VALUES.values()); while (options.size() < 4) { - options.add(allValues.get(RANDOM.nextInt(allValues.size()))); + String wrong = allValues.get(RANDOM.nextInt(allValues.size())); + if (wrong != null) options.add(wrong); } + return new ArrayList<>(options); } @@ -52,4 +142,15 @@ public class HighQuestionGenerator implements QuestionGenerator { Collections.shuffle(options); return options.indexOf(correctAnswer); } -} + + /** + * 一次性生成指定数量的题目 + */ + public List generateQuestions(int count) { + List questions = new ArrayList<>(); + for (int i = 0; i < count; i++) { + questions.add(generateQuestion()); + } + return questions; + } +} \ No newline at end of file diff --git a/src/main/java/com/student/mathquiz/question/PrimaryQuestionGenerator.java b/src/main/java/com/student/mathquiz/question/PrimaryQuestionGenerator.java index 11a28d5..ec28d0f 100644 --- a/src/main/java/com/student/mathquiz/question/PrimaryQuestionGenerator.java +++ b/src/main/java/com/student/mathquiz/question/PrimaryQuestionGenerator.java @@ -9,19 +9,15 @@ public class PrimaryQuestionGenerator implements QuestionGenerator { @Override public Question generateQuestion() { - int operandCount = RANDOM.nextInt(2) + 2; + // 操作数数量2-5个 + int operandCount = RANDOM.nextInt(4) + 2; // nextInt(4)→0-3,+2→2-5 List operands = new ArrayList<>(); List ops = new ArrayList<>(); - for (int i = 0; i < operandCount; i++) { - operands.add(RANDOM.nextInt(100) + 1); - } - for (int i = 0; i < operandCount - 1; i++) { - ops.add(OPERATORS[RANDOM.nextInt(OPERATORS.length)]); - } - - handleDivision(operands, ops); + // 生成合法表达式(修复后) + buildValidExpression(operands, ops, operandCount); + // 拼接题目内容 StringBuilder contentSb = new StringBuilder(); for (int i = 0; i < operandCount; i++) { contentSb.append(operands.get(i)); @@ -30,27 +26,135 @@ public class PrimaryQuestionGenerator implements QuestionGenerator { } } String content = contentSb.toString() + " = ?"; + + // 计算正确答案 String correctAnswer = calculateAnswer(operands, ops); + + // 生成选项 List options = generateOptions(correctAnswer); + + // 打乱选项 int correctIndex = shuffleOptions(options, correctAnswer); + return new Question(content, correctAnswer, options, correctIndex); } - private void handleDivision(List operands, List ops) { - for (int i = 0; i < ops.size(); i++) { - if (ops.get(i) == '/') { - int divisor = operands.get(i + 1); - if (divisor == 0) { - divisor = 1; - operands.set(i + 1, divisor); + /** + * 修复核心:确保operands和ops长度匹配(operands.size() = ops.size() + 1) + * 每次循环只添加1个运算符+1个操作数,避免重复 + */ + private void buildValidExpression(List operands, List ops, int operandCount) { + // 第一个操作数:1-50 + int firstOperand = RANDOM.nextInt(50) + 1; + operands.add(firstOperand); + + // 循环生成“1个运算符+1个操作数”(共operandCount-1组) + for (int i = 0; i < operandCount - 1; i++) { + int nextOperand; + char op; + // 循环重试:直到生成能让中间结果非负的组合 + while (true) { + // 1. 只生成1个运算符(无重复) + op = OPERATORS[RANDOM.nextInt(OPERATORS.length)]; + // 2. 计算当前中间结果(此时ops还没加新op,operands也没加新数,长度匹配) + int currentMidResult = tempCalculate(operands, ops); + // 3. 基于当前中间结果生成合法操作数 + nextOperand = generateValidNextOperand(currentMidResult, op); + // 4. 临时添加运算符和操作数(此时才开始添加,确保成对) + ops.add(op); + operands.add(nextOperand); + // 5. 检查新的中间结果是否非负 + int newMidResult = tempCalculate(operands, ops); + if (newMidResult >= 0) { + // 合格,保留当前组合 + break; + } else { + // 不合格,回滚(移除刚加的运算符和操作数,长度恢复匹配) + ops.remove(ops.size() - 1); + operands.remove(operands.size() - 1); } - int quotient = RANDOM.nextInt(10) + 1; - operands.set(i, divisor * quotient); } } } + /** + * 临时计算中间结果(无修改,确保参数长度匹配即可) + */ + private int tempCalculate(List tempOperands, List tempOps) { + // 防御性判断:避免极端情况下长度不匹配 + if (tempOperands.size() != tempOps.size() + 1) { + return -1; // 触发重试 + } + + List nums = new ArrayList<>(tempOperands); + List operators = new ArrayList<>(tempOps); + + // 先处理乘除 + int i = 0; + while (i < operators.size()) { + char op = operators.get(i); + if (op == '*' || op == '/') { + int left = nums.get(i); + int right = nums.get(i + 1); // 现在长度匹配,不会越界 + int result = (op == '*') ? left * right : left / right; + nums.set(i, result); + nums.remove(i + 1); + operators.remove(i); + } else { + i++; + } + } + + // 再处理加减 + int midResult = nums.get(0); + for (i = 0; i < operators.size(); i++) { + int next = nums.get(i + 1); + midResult = (operators.get(i) == '+') ? midResult + next : midResult - next; + } + return midResult; + } + + /** + * 生成合法操作数 + */ + private int generateValidNextOperand(int currentMidResult, char op) { + switch (op) { + case '+': + return RANDOM.nextInt(30) + 1; + case '-': + // 基于中间结果生成,确保非负 + return currentMidResult <= 0 ? 1 : RANDOM.nextInt(currentMidResult) + 1; + case '*': + return RANDOM.nextInt(5) + 1; + case '/': + List divisors = getDivisors(currentMidResult); + return divisors.get(RANDOM.nextInt(divisors.size())); + default: + return 1; + } + } + + /** + * 获取除数 + */ + private List getDivisors(int num) { + List divisors = new ArrayList<>(); + for (int i = 1; i <= num / 2; i++) { + if (num % i == 0) { + divisors.add(i); + } + } + if (divisors.isEmpty()) { + divisors.add(1); + } + return divisors; + } + + /** + * 计算答案 + */ private String calculateAnswer(List operands, List ops) { +<<<<<<< HEAD // Simplified calculation for primary school (no operator precedence) int result = operands.get(0); for (int i = 0; i < ops.size(); i++) { @@ -68,39 +172,68 @@ public class PrimaryQuestionGenerator implements QuestionGenerator { case '/': result /= nextOperand; break; +======= + List nums = new ArrayList<>(operands); + List operators = new ArrayList<>(ops); + + // 先处理乘除 + int i = 0; + while (i < operators.size()) { + char op = operators.get(i); + if (op == '*' || op == '/') { + int left = nums.get(i); + int right = nums.get(i + 1); + int result = (op == '*') ? left * right : left / right; + nums.set(i, result); + nums.remove(i + 1); + operators.remove(i); + } else { + i++; +>>>>>>> develop + } + } + + // 再处理加减 + int finalResult = nums.get(0); + for (i = 0; i < operators.size(); i++) { + int next = nums.get(i + 1); + switch (operators.get(i)) { + case '+': + finalResult += next; + break; + case '-': + finalResult -= next; + break; } } - return String.valueOf(result); + + return String.valueOf(finalResult); } - // 在 PrimaryQuestionGenerator.java 中 + /** + * 生成选项 + */ private List generateOptions(String correctAnswer) { - Set options = new HashSet<>(); // 使用Set来自动处理重复问题 + Set options = new HashSet<>(); options.add(correctAnswer); int correctNum = Integer.parseInt(correctAnswer); - // ★★★ 修正后的逻辑 ★★★ while (options.size() < 4) { - int offset = RANDOM.nextInt(20) + 1; // 偏移量 1-20 - // 随机生成一个错误答案,确保它不等于正确答案 - int wrongNum = (RANDOM.nextBoolean()) ? correctNum + offset : correctNum - offset; - - // 确保错误答案是正数且不等于正确答案 - if (wrongNum > 0 && wrongNum != correctNum) { - options.add(String.valueOf(wrongNum)); - } else { - // 如果生成的不好,就再生成一个绝对不会重复的 - options.add(String.valueOf(correctNum + options.size() + 1)); + int offset = RANDOM.nextInt(20) + 1; + int wrongNum = RANDOM.nextBoolean() ? correctNum + offset : correctNum - offset; + if (wrongNum <= 0) { + wrongNum = correctNum + offset + 10; } + options.add(String.valueOf(wrongNum)); } - - List result = new ArrayList<>(options); - return result; // 返回最终的选项列表 + return new ArrayList<>(options); } - + /** + * 打乱选项 + */ private int shuffleOptions(List options, String correctAnswer) { Collections.shuffle(options); return options.indexOf(correctAnswer); } -} +} \ No newline at end of file diff --git a/src/main/java/com/student/mathquiz/service/IUserService.java b/src/main/java/com/student/mathquiz/service/IUserService.java index 4b2c774..12367e7 100644 --- a/src/main/java/com/student/mathquiz/service/IUserService.java +++ b/src/main/java/com/student/mathquiz/service/IUserService.java @@ -1,8 +1,11 @@ package com.student.mathquiz.service; +import com.student.mathquiz.model.User; // ★★★ 确保导入了这个类 ★★★ + public interface IUserService { boolean sendVerificationCode(String email); +<<<<<<< HEAD // ★★★ 修改 register 方法,加入 username 参数 ★★★ String register(String username, String email, String code, String password, @@ -10,6 +13,12 @@ public interface IUserService { // ★★★ 修改 login 方法,参数从 email 改为 identifier (标识符) ★★★ boolean login(String identifier, String password); +======= + String register(String username, String email, String code, String password, String confirmPassword); + + // ★★★ 修改这里的返回类型 ★★★ + User login(String identifier, String password); +>>>>>>> develop String changePassword(String email, String oldPassword, String newPassword1, String newPassword2); } diff --git a/src/main/java/com/student/mathquiz/service/UserServiceImpl.java b/src/main/java/com/student/mathquiz/service/UserServiceImpl.java index 8e905dc..2eb8a10 100644 --- a/src/main/java/com/student/mathquiz/service/UserServiceImpl.java +++ b/src/main/java/com/student/mathquiz/service/UserServiceImpl.java @@ -120,17 +120,16 @@ public class UserServiceImpl implements IUserService { return null; } - // ★★★ 用这个新版本替换掉旧的 login 方法 ★★★ + + // 在 UserServiceImpl.java 中 @Override - public boolean login(String identifier, String password) { + public User login(String identifier, String password) { User user = null; // 智能判断是邮箱还是用户名 if (identifier.contains("@")) { - // 按邮箱登录 user = userDatabase.get(identifier); } else { - // 按用户名登录,需要遍历查找 for (User u : userDatabase.values()) { if (u.getUsername().equalsIgnoreCase(identifier)) { user = u; @@ -139,17 +138,21 @@ public class UserServiceImpl implements IUserService { } } - // 如果找不到用户,直接返回失败 if (user == null) { - return false; + return null; // 找不到用户,返回 null } - // 找到用户后,验证密码(逻辑和以前一样) + // 验证密码 String encryptedInputPwd = Base64.getEncoder().encodeToString(password.getBytes()); - return user.getEncryptedPwd().equals(encryptedInputPwd); + if (user.getEncryptedPwd().equals(encryptedInputPwd)) { + return user; // ★★★ 密码正确,返回整个 User 对象! ★★★ + } else { + return null; // 密码错误,返回 null + } } + @Override public String changePassword(String email, String oldPassword, String newPassword1, String newPassword2) { diff --git a/src/main/java/com/student/mathquiz/view/LoginViewController.java b/src/main/java/com/student/mathquiz/view/LoginViewController.java index ecc2fd3..8acc8bd 100644 --- a/src/main/java/com/student/mathquiz/view/LoginViewController.java +++ b/src/main/java/com/student/mathquiz/view/LoginViewController.java @@ -24,17 +24,24 @@ public class LoginViewController { this.userService = mainApp.getUserService(); } + // 在 LoginViewController.java 中 @FXML private void handleLogin() { - String email = emailField.getText(); + String identifier = emailField.getText(); // 我们把变量名改得更准确 String password = passwordField.getText(); - if (userService.login(email, password)) { - mainApp.handleLoginSuccess(email); + + // ★★★ 调用新的 login 方法,它会返回一个 User 对象 ★★★ + com.student.mathquiz.model.User loggedInUser = userService.login(identifier, password); + + if (loggedInUser != null) { // 如果返回的不是 null,说明登录成功 + // ★★★ 把完整的 User 对象传给 MainApp ★★★ + mainApp.handleLoginSuccess(loggedInUser); } else { - statusLabel.setText("邮箱或密码错误!"); + statusLabel.setText("用户名/邮箱或密码错误!"); } } + @FXML private void handleGoToRegister() { mainApp.showRegisterView(); diff --git a/user_data/users.json b/user_data/users.json index 9840f3f..dc6dd59 100644 --- a/user_data/users.json +++ b/user_data/users.json @@ -2,7 +2,7 @@ { "username": "清清", "email": "lyqqqq1214@163.com", - "encryptedPwd": "NjY2NjY2bEw\u003d", + "encryptedPwd": "MTIzNDU2bEw\u003d", "userType": "PRIMARY" } -] +] \ No newline at end of file