pull/4/head
commit
1299f6fe5e
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@ -0,0 +1,3 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
@ -0,0 +1 @@
|
||||
UserService.java
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="23" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,17 @@
|
||||
[ {
|
||||
"username" : "LXR",
|
||||
"email" : "2759462569@qq.com",
|
||||
"passwordHash" : "$2a$12$AiupZKqpZMXvstX6XYNGUuBDZOMdzqXy/ADaYzurUYatM293Lbxii",
|
||||
"registrationDate" : [ 2025, 10, 11, 19, 40, 59, 177105400 ],
|
||||
"verificationCode" : "371978",
|
||||
"verified" : true,
|
||||
"type" : "高中"
|
||||
}, {
|
||||
"username" : "小鱼",
|
||||
"email" : "1280556515@qq.com",
|
||||
"passwordHash" : "$2a$12$dbNwBK6NBj7mXU6YzNMAweTMhD9NOxsjPGzW2SfIM.QvGdWt7Lyvy",
|
||||
"registrationDate" : [ 2025, 10, 10, 11, 7, 5, 853200500 ],
|
||||
"verificationCode" : "688201",
|
||||
"verified" : true,
|
||||
"type" : "高中"
|
||||
} ]
|
||||
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.mathlearning</groupId>
|
||||
<artifactId>math-learning-app</artifactId>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- JavaMail for email verification -->
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON processing -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.15.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.15.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Password hashing -->
|
||||
<dependency>
|
||||
<groupId>at.favre.lib</groupId>
|
||||
<artifactId>bcrypt</artifactId>
|
||||
<version>0.9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -0,0 +1,324 @@
|
||||
package mathlearning.ui;
|
||||
|
||||
import mathlearning.model.User;
|
||||
import mathlearning.service.MultipleChoiceGenerator.MultipleChoiceGenerator;
|
||||
import mathlearning.service.UserService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class SelTestFrame extends JFrame {
|
||||
private MainFrame mainFrame;
|
||||
private User user;
|
||||
private UserService userService;
|
||||
private MultipleChoiceGenerator multipleChoiceGenerator;
|
||||
|
||||
private int questionNum;
|
||||
private int currentQuestionDex;
|
||||
private String[] answers;
|
||||
private String[] myAnswers;
|
||||
|
||||
private JLabel titleLabel;
|
||||
private JButton optionA;
|
||||
private JButton optionB;
|
||||
private JButton optionC;
|
||||
private JButton optionD;
|
||||
private JButton prevButton;
|
||||
private JButton nextButton;
|
||||
private JButton submitButton;
|
||||
private JLabel question;
|
||||
private JLabel choice;
|
||||
|
||||
public SelTestFrame(MainFrame mainFrame, User user, UserService userService, int num) {
|
||||
this.mainFrame = mainFrame;
|
||||
this.user = user;
|
||||
this.userService = userService;
|
||||
this.questionNum = num;
|
||||
this.currentQuestionDex = 0;
|
||||
this.myAnswers = new String[questionNum];
|
||||
this.multipleChoiceGenerator = new MultipleChoiceGenerator(num, user);
|
||||
this.answers = multipleChoiceGenerator.GetCorrectAnswerNo();
|
||||
InitUI();
|
||||
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
handleCloseOperation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void InitUI() {
|
||||
setTitle("答题界面");
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
setSize(800, 600);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
//主面板
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
|
||||
//上
|
||||
titleLabel = new JLabel("当前为:第" + (currentQuestionDex + 1) + "题");
|
||||
|
||||
//左侧面板
|
||||
JPanel leftPanel = createLeftPanel();
|
||||
|
||||
//中
|
||||
JPanel centerPanel = centerPanel();
|
||||
|
||||
//右
|
||||
JPanel rightPanel = createRightPanel();
|
||||
|
||||
//底
|
||||
JPanel bottomPanel = createButtonPanel();
|
||||
|
||||
mainPanel.add(titleLabel, BorderLayout.NORTH);
|
||||
mainPanel.add(leftPanel, BorderLayout.WEST);
|
||||
mainPanel.add(centerPanel, BorderLayout.CENTER);
|
||||
mainPanel.add(rightPanel, BorderLayout.EAST);
|
||||
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
add(mainPanel);
|
||||
|
||||
updateNavigationButtons();
|
||||
}
|
||||
|
||||
private JPanel createLeftPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
JLabel usernameLabel = new JLabel("用户:" + user.getUsername());
|
||||
usernameLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
||||
usernameLabel.setForeground(Color.BLUE);
|
||||
panel.add(usernameLabel, BorderLayout.NORTH);
|
||||
|
||||
JList<String> questionList = new JList<>();
|
||||
String[] questions = new String[questionNum + 1];
|
||||
for (int i = 0; i < questionNum; i++) {
|
||||
questions[i] = "题目" + (i + 1);
|
||||
}
|
||||
questionList.setListData(questions);
|
||||
panel.add(questionList, BorderLayout.CENTER);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel centerPanel() {
|
||||
JPanel panel = new JPanel(new GridLayout(6, 1));
|
||||
|
||||
JLabel questionLabel = new JLabel("题目:");
|
||||
questionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||
question = new JLabel(multipleChoiceGenerator.GetQuestionList()[currentQuestionDex]);
|
||||
question.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||
panel.add(questionLabel);
|
||||
panel.add(question);
|
||||
|
||||
JLabel choiceLabel = new JLabel("选项:");
|
||||
choiceLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||
choice = new JLabel(multipleChoiceGenerator.GetChoiceList()[currentQuestionDex]);
|
||||
choiceLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
||||
panel.add(choiceLabel);
|
||||
panel.add(choice);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel createRightPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
JLabel titleLabel = new JLabel("作答区域:");
|
||||
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
||||
panel.add(titleLabel, BorderLayout.NORTH);
|
||||
|
||||
JPanel buttonPanel = new JPanel(new GridLayout(4, 1));
|
||||
|
||||
optionA = new JButton("A");
|
||||
optionA.setBackground(Color.LIGHT_GRAY);
|
||||
optionA.setForeground(Color.BLACK);
|
||||
optionA.addActionListener(e -> saveAnswer("A"));
|
||||
optionB = new JButton("B");
|
||||
optionB.setBackground(Color.LIGHT_GRAY);
|
||||
optionB.setForeground(Color.BLACK);
|
||||
optionB.addActionListener(e -> saveAnswer("B"));
|
||||
optionC = new JButton("C");
|
||||
optionC.setBackground(Color.LIGHT_GRAY);
|
||||
optionC.setForeground(Color.BLACK);
|
||||
optionC.addActionListener(e -> saveAnswer("C"));
|
||||
optionD = new JButton("D");
|
||||
optionD.setBackground(Color.LIGHT_GRAY);
|
||||
optionD.setForeground(Color.BLACK);
|
||||
optionD.addActionListener(e -> saveAnswer("D"));
|
||||
buttonPanel.add(optionA);
|
||||
buttonPanel.add(optionB);
|
||||
buttonPanel.add(optionC);
|
||||
buttonPanel.add(optionD);
|
||||
panel.add(buttonPanel, BorderLayout.CENTER);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel createButtonPanel() {
|
||||
JPanel panel = new JPanel(new FlowLayout());
|
||||
|
||||
prevButton = new JButton("上一题");
|
||||
prevButton.addActionListener(e -> goToPrevQuestion());
|
||||
|
||||
nextButton = new JButton("下一题");
|
||||
nextButton.addActionListener(e -> goToNextQuestion());
|
||||
|
||||
submitButton = new JButton("提交");
|
||||
submitButton.addActionListener(e -> goToSubmit());
|
||||
|
||||
panel.add(prevButton);
|
||||
panel.add(nextButton);
|
||||
panel.add(submitButton);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void saveAnswer(String answer) {
|
||||
resetButtonColors();
|
||||
|
||||
switch (answer) {
|
||||
case "A":
|
||||
optionA.setBackground(Color.GREEN);
|
||||
myAnswers[currentQuestionDex] = answer;
|
||||
break;
|
||||
case "B":
|
||||
optionB.setBackground(Color.GREEN);
|
||||
myAnswers[currentQuestionDex] = answer;
|
||||
break;
|
||||
case "C":
|
||||
optionC.setBackground(Color.GREEN);
|
||||
myAnswers[currentQuestionDex] = answer;
|
||||
break;
|
||||
case "D":
|
||||
optionD.setBackground(Color.GREEN);
|
||||
myAnswers[currentQuestionDex] = answer;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void resetButtonColors() {
|
||||
optionA.setBackground(Color.LIGHT_GRAY);
|
||||
optionB.setBackground(Color.LIGHT_GRAY);
|
||||
optionC.setBackground(Color.LIGHT_GRAY);
|
||||
optionD.setBackground(Color.LIGHT_GRAY);
|
||||
}
|
||||
|
||||
private void goToPrevQuestion() {
|
||||
if (currentQuestionDex > 0) {
|
||||
currentQuestionDex--;
|
||||
updateTitleLabel();
|
||||
updateQuestion();
|
||||
if (myAnswers[currentQuestionDex] == null) {
|
||||
resetButtonColors();
|
||||
}
|
||||
else {
|
||||
saveAnswer(myAnswers[currentQuestionDex]);
|
||||
}
|
||||
|
||||
updateNavigationButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private void goToNextQuestion() {
|
||||
if (currentQuestionDex < questionNum - 1) {
|
||||
currentQuestionDex++;
|
||||
updateTitleLabel();
|
||||
updateQuestion();
|
||||
if (myAnswers[currentQuestionDex] == null) {
|
||||
resetButtonColors();
|
||||
} else {
|
||||
saveAnswer(myAnswers[currentQuestionDex]);
|
||||
}
|
||||
|
||||
updateNavigationButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private void goToSubmit() {
|
||||
int confirm = JOptionPane.showConfirmDialog(SelTestFrame.this, "你确定要提交试卷吗?", "提示", JOptionPane.YES_NO_OPTION);
|
||||
if (confirm == JOptionPane.YES_OPTION) {
|
||||
int correctCount = 0;
|
||||
correctCount = getScore(answers, myAnswers);
|
||||
|
||||
double accuracy = Math.round((double) correctCount / myAnswers.length * 10000) / 100.0;
|
||||
double score = Math.round((double) correctCount * 100 / myAnswers.length * 10) / 10.0;
|
||||
|
||||
// 弹出分数结果
|
||||
String[] options = {"返回主菜单", "继续做题"};
|
||||
int choice = JOptionPane.showOptionDialog(
|
||||
SelTestFrame.this,
|
||||
"您答对了" + correctCount + "道题,正确率为" + String.format("%.2f", accuracy) + "\n您的得分是: " + score + "分",
|
||||
"测试结果",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.INFORMATION_MESSAGE,
|
||||
null,
|
||||
options,
|
||||
options[0]
|
||||
);
|
||||
|
||||
if (choice == 0) {
|
||||
mainFrame.setVisible(true);
|
||||
dispose();
|
||||
} else if (choice == 1) {
|
||||
dispose();
|
||||
mainFrame.setVisible(true);
|
||||
mainFrame.reTryTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNavigationButtons() {
|
||||
if (currentQuestionDex == 0) {
|
||||
prevButton.setEnabled(false);
|
||||
prevButton.setVisible(false);
|
||||
}
|
||||
else {
|
||||
prevButton.setEnabled(true);
|
||||
prevButton.setVisible(true);
|
||||
}
|
||||
|
||||
if (currentQuestionDex == questionNum - 1) {
|
||||
nextButton.setEnabled(false);
|
||||
nextButton.setVisible(false);
|
||||
submitButton.setEnabled(true);
|
||||
submitButton.setVisible(true);
|
||||
} else {
|
||||
nextButton.setEnabled(true);
|
||||
nextButton.setVisible(true);
|
||||
submitButton.setEnabled(false);
|
||||
submitButton.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTitleLabel() {
|
||||
titleLabel.setText("当前为:第" + (currentQuestionDex + 1) + "题");
|
||||
}
|
||||
|
||||
private void handleCloseOperation() {
|
||||
int result = JOptionPane.showConfirmDialog(SelTestFrame.this, "确定要中途退出答题吗?当前答题进度将会丢失!", "确认退出", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
mainFrame.setVisible(true);
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private int getScore(String[] answers, String[] myAnswers) {
|
||||
if (answers == null || myAnswers == null){
|
||||
return 0;
|
||||
}
|
||||
int score = 0;
|
||||
for (int i = 0; i < answers.length; i++) {
|
||||
if (answers[i] != null && answers[i].equals(myAnswers[i])){
|
||||
score++;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
private void updateQuestion() {
|
||||
question.setText(multipleChoiceGenerator.GetQuestionList()[currentQuestionDex]);
|
||||
choice.setText(multipleChoiceGenerator.GetChoiceList()[currentQuestionDex]);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue