Merge pull request '最终版1.5' (#9) from develop into main
commit
3141d0accd
@ -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,27 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="MathLearningApp:jar">
|
||||
<output-path>$PROJECT_DIR$/target</output-path>
|
||||
<root id="archive" name="MathLearningApp.jar">
|
||||
<element id="directory" name="META-INF">
|
||||
<element id="file-copy" path="$PROJECT_DIR$/out/META-INF/MANIFEST.MF" />
|
||||
</element>
|
||||
<element id="module-output" name="MathLearningApp" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/sun/mail/javax.mail/1.6.2/javax.mail-1.6.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/at/favre/lib/bcrypt/0.9.0/bcrypt-0.9.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/at/favre/lib/bytes/1.3.0/bytes-1.3.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.15.2/jackson-datatype-jsr310-2.15.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.15.2/jackson-core-2.15.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/javax/activation/activation/1.1/activation-1.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.15.2/jackson-databind-2.15.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.15.2/jackson-annotations-2.15.2.jar" path-in-jar="/" />
|
||||
<element id="library" level="project" name="Maven: com.sun.mail:javax.mail:1.6.2" />
|
||||
<element id="library" level="project" name="Maven: javax.activation:activation:1.1" />
|
||||
<element id="library" level="project" name="Maven: com.fasterxml.jackson.core:jackson-core:2.15.2" />
|
||||
<element id="library" level="project" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.15.2" />
|
||||
<element id="library" level="project" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.15.2" />
|
||||
<element id="library" level="project" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2" />
|
||||
<element id="library" level="project" name="Maven: at.favre.lib:bcrypt:0.9.0" />
|
||||
<element id="library" level="project" name="Maven: at.favre.lib:bytes:1.3.0" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
@ -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>
|
||||
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<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_23" default="true" project-jdk-name="23" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<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,24 @@
|
||||
package mathlearning;
|
||||
|
||||
import mathlearning.service.UserService;
|
||||
import mathlearning.ui.LoginFrame;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
// 设置UI风格
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 启动应用程序
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
UserService userService = new UserService();
|
||||
LoginFrame loginFrame = new LoginFrame(userService);
|
||||
loginFrame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package mathlearning.model;
|
||||
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class User {
|
||||
private String username;
|
||||
private String email;
|
||||
private String passwordHash;
|
||||
private LocalDateTime registrationDate;
|
||||
private String verificationCode;
|
||||
private boolean verified;
|
||||
private String type;
|
||||
|
||||
public User( ) {}
|
||||
|
||||
public User(String email, String passwordHash, String verificationCode) {
|
||||
this.email = email;
|
||||
this.passwordHash = passwordHash;
|
||||
this.verificationCode = verificationCode;
|
||||
this.verified = false;
|
||||
this.registrationDate = LocalDateTime.now();
|
||||
this.type = null;
|
||||
}
|
||||
|
||||
// Getters and setters
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getPasswordHash() { return passwordHash; }
|
||||
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
|
||||
|
||||
public String getVerificationCode() { return verificationCode; }
|
||||
public void setVerificationCode(String verificationCode) { this.verificationCode = verificationCode; }
|
||||
|
||||
public boolean isVerified() { return verified; }
|
||||
public void setVerified(boolean verified) { this.verified = verified; }
|
||||
|
||||
public LocalDateTime getRegistrationDate() { return registrationDate; }
|
||||
public void setRegistrationDate(LocalDateTime registrationDate) { this.registrationDate = registrationDate; }
|
||||
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) {this.username = username; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package mathlearning.service;
|
||||
|
||||
import javax.mail.*;
|
||||
import javax.mail.internet.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class EmailService {
|
||||
private final String host;
|
||||
private final String port;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final boolean auth;
|
||||
|
||||
public EmailService(String host, String port, String username, String password, boolean auth) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public boolean sendVerificationCode(String toEmail, String verificationCode, int flag) {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
props.put("mail.smtp.host", host);
|
||||
props.put("mail.smtp.port", port);
|
||||
props.put("mail.smtp.auth", auth);
|
||||
props.put("mail.smtp.starttls.enable", "true");
|
||||
|
||||
Session session = Session.getInstance(props, new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
|
||||
Message message = new MimeMessage(session);
|
||||
message.setFrom(new InternetAddress(username));
|
||||
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
|
||||
message.setSubject("数学学习软件 - 注册验证码");
|
||||
String emailContent="";
|
||||
|
||||
if (flag == 1) emailContent = registerContent(verificationCode);
|
||||
else if (flag == 2) emailContent = resetPasswordContent(verificationCode);
|
||||
|
||||
|
||||
message.setText(emailContent);
|
||||
|
||||
Transport.send(message);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String registerContent(String verificationCode) {
|
||||
return "尊敬的用户:\n\n" +
|
||||
"您的注册验证码是:" + verificationCode + "\n\n" +
|
||||
"该验证码有效期为10分钟。\n\n" +
|
||||
"如果您没有注册本软件,请忽略此邮件。\n\n" +
|
||||
"数学学习软件团队";
|
||||
}
|
||||
|
||||
public String resetPasswordContent(String verificationCode) {
|
||||
return "尊敬的用户:\n\n" +
|
||||
"您的重置验证码是:" + verificationCode + "\n\n" +
|
||||
"该验证码有效期为10分钟。\n\n" +
|
||||
"如果您没有重置密码,请忽略此邮件。\n\n" +
|
||||
"数学学习软件团队";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
package mathlearning.service.MultipleChoiceGenerator;
|
||||
import mathlearning.model.User;
|
||||
import mathlearning.service.QuestionGenerator.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MultipleChoiceGenerator {
|
||||
private static QuestionGenerator QuestionGenerator = new PrimaryGenerator();
|
||||
String[] QuestionList ;
|
||||
String[] AnswerList ;
|
||||
String[] ChoiceList ;
|
||||
String[] CorrectAnswerNo;
|
||||
|
||||
public MultipleChoiceGenerator(int count, User nowUser){// 如此声明MultipleChoiceGenerator实例,再调用下面三个接口
|
||||
this.QuestionList = new String[count];
|
||||
this.ChoiceList = new String[count];
|
||||
this.CorrectAnswerNo = new String[count];
|
||||
this.QuestionList = SetQuestionList(count, nowUser);
|
||||
SetChoiceList();
|
||||
}
|
||||
|
||||
public String[] GetQuestionList(){
|
||||
return this.QuestionList;
|
||||
}
|
||||
|
||||
public String[] GetChoiceList(){
|
||||
return this.ChoiceList;
|
||||
}
|
||||
|
||||
public String[] GetAnswerList(){
|
||||
return this.AnswerList;
|
||||
}
|
||||
|
||||
public String[] GetCorrectAnswerNo(){
|
||||
return this.CorrectAnswerNo;
|
||||
}
|
||||
|
||||
private void SetChoiceList(){
|
||||
for(int i = 0 ; i < this.AnswerList.length ; i++){
|
||||
Random random = new Random();
|
||||
String[] choiceNo = {"A","B","C","D"};
|
||||
String[] choices = new String[4];
|
||||
double correctChoice = Double.parseDouble(this.AnswerList[i]);
|
||||
int position = random.nextInt(4);
|
||||
choices[position] = choiceNo[position] + String.format("%.2f", correctChoice);
|
||||
|
||||
|
||||
for(int j = 0 ; j < 4 ; j++){
|
||||
if(j != position){
|
||||
double choice = correctChoice;
|
||||
double offset = random.nextInt(41) - 20;
|
||||
choice += offset;
|
||||
choices[j] =choiceNo[j] +"." + String.format("%.2f", choice);
|
||||
}
|
||||
else{
|
||||
CorrectAnswerNo[i] = choiceNo[j];
|
||||
}
|
||||
}
|
||||
|
||||
this.ChoiceList[i] = String.join(" ", choices);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] SetQuestionList(int count, User nowUser){
|
||||
String[] Questions= new String[count];
|
||||
if(nowUser.getType().equals("小学") ) {
|
||||
QuestionGenerator = new PrimaryGenerator();
|
||||
}
|
||||
else if( nowUser.getType().equals("初中") ) {
|
||||
QuestionGenerator = new middleGenerator();
|
||||
}
|
||||
else if( nowUser.getType().equals("高中") ) {
|
||||
QuestionGenerator = new highGenerator();
|
||||
}
|
||||
|
||||
List<String> questions = new ArrayList<>();
|
||||
Set<String> generatedQuestions = new HashSet<>();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
String question;
|
||||
do {
|
||||
question = QuestionGenerator.generateQuestion();
|
||||
} while ( generatedQuestions.contains(question ));
|
||||
generatedQuestions.add(question);
|
||||
questions.add(question);
|
||||
}
|
||||
|
||||
for(int i = 0 ; i< count ; i++){
|
||||
Questions[i] = questions.get(i);
|
||||
}
|
||||
this.AnswerList = new String[count];
|
||||
for(int i = 0 ; i< count ; i++){
|
||||
ComputingUnit computingUnit = new ComputingUnit(Questions[i]);
|
||||
this.AnswerList[i] = computingUnit.getAnswer();
|
||||
}
|
||||
return Questions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package mathlearning.service.MultipleChoiceGenerator;
|
||||
|
||||
import mathlearning.model.User;
|
||||
|
||||
public class MultipleChoiceGeneratorTest {
|
||||
public static void main(String[] args) {
|
||||
// 创建一个模拟用户
|
||||
User testUser = new User();
|
||||
testUser.setType("小学"); // 可以分别测试"小学"、"初中"、"高中"
|
||||
|
||||
// 测试生成10道题目
|
||||
int questionCount = 10;
|
||||
MultipleChoiceGenerator generator = new MultipleChoiceGenerator(questionCount, testUser);
|
||||
|
||||
// 获取生成的题目、答案和选项
|
||||
String[] questions = generator.GetQuestionList();
|
||||
String[] answers = generator.GetAnswerList();
|
||||
String[] choices = generator.GetChoiceList();
|
||||
|
||||
// 输出测试结果
|
||||
System.out.println("=== 数学题目生成测试 ===");
|
||||
System.out.println("用户类型: " + testUser.getType());
|
||||
System.out.println("生成题目数量: " + questionCount);
|
||||
System.out.println();
|
||||
|
||||
for (int i = 0; i < questions.length; i++) {
|
||||
System.out.println("题目 " + (i + 1) + ": " + questions[i]);
|
||||
System.out.println("答案: " + answers[i]);
|
||||
System.out.println("选项:");
|
||||
String[] choiceArray = choices[i].split("\n");
|
||||
for (int j = 0; j < choiceArray.length; j++) {
|
||||
System.out.println(" " + (char)('A' + j) + ". " + choiceArray[j]);
|
||||
}
|
||||
System.out.println("----------------------------------------");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package mathlearning.service.QuestionGenerator;
|
||||
|
||||
public class PrimaryGenerator extends QuestionGenerator{
|
||||
public PrimaryGenerator() {
|
||||
super("小学");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateQuestion() {
|
||||
|
||||
int operandCount = random.nextInt(4) + 2;
|
||||
|
||||
// 生成操作数
|
||||
int[] operands = new int[operandCount];
|
||||
for (int i = 0; i < operandCount; i++) {
|
||||
operands[i] = random.nextInt(100) + 1; // 1-100
|
||||
}
|
||||
|
||||
String question = preForOper(operands);
|
||||
return addParen(question);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package mathlearning.service.QuestionGenerator;
|
||||
|
||||
public class highGenerator extends QuestionGenerator{
|
||||
|
||||
public highGenerator() {
|
||||
super("高中");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateQuestion() {
|
||||
int operandCount = random.nextInt(4) + 2;
|
||||
|
||||
// 生成操作数
|
||||
int[] operands = new int[ operandCount ];
|
||||
for (int i = 0; i < operandCount; i++) {
|
||||
operands[i] = random.nextInt(100) + 1; // 1-100
|
||||
}
|
||||
|
||||
String question = preForOper( operands );
|
||||
question = add_squs( question );
|
||||
question = add_sins( question );
|
||||
return addParen( question );
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package mathlearning.service.QuestionGenerator;
|
||||
|
||||
public class middleGenerator extends QuestionGenerator{
|
||||
|
||||
public middleGenerator() {
|
||||
super("初中");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateQuestion() {
|
||||
int operandCount = random.nextInt(4) + 2;
|
||||
|
||||
// 生成操作数
|
||||
int[] operands = new int [ operandCount ];
|
||||
for (int i = 0; i < operandCount; i++) {
|
||||
operands[i] = random.nextInt(100) + 1; // 1-100
|
||||
}
|
||||
|
||||
String question = preForOper(operands);
|
||||
question = add_squs(question);
|
||||
return addParen(question);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,251 @@
|
||||
package mathlearning.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import mathlearning.model.User;
|
||||
import at.favre.lib.crypto.bcrypt.BCrypt;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class UserService {
|
||||
private static final String USERS_FILE = "data/users.json";
|
||||
private static final long VERIFICATION_CODE_EXPIRY_MINUTES = 10;
|
||||
|
||||
private Map<String, User> users;
|
||||
private Map<String, LocalDateTime> verificationCodeTimestamps;
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
public UserService() {
|
||||
this.users = new ConcurrentHashMap<>();
|
||||
this.verificationCodeTimestamps = new ConcurrentHashMap<>();
|
||||
this.objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new JavaTimeModule());
|
||||
loadUsers();
|
||||
}
|
||||
|
||||
private void loadUsers() {
|
||||
try {
|
||||
File file = new File(USERS_FILE);
|
||||
if (file.exists() && file.length() > 0) {
|
||||
User[] userArray = objectMapper.readValue(file, User[].class);
|
||||
for (User user : userArray) {
|
||||
users.put(user.getEmail(), user);
|
||||
}
|
||||
System.out.println("成功加载 " + userArray.length + " 个用户");
|
||||
} else {
|
||||
saveUsers();
|
||||
System.out.println("创建新的用户数据文件");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("加载用户数据失败: " + e.getMessage());
|
||||
backupAndRecreateFile();
|
||||
}
|
||||
}
|
||||
|
||||
private void backupAndRecreateFile() {
|
||||
try {
|
||||
File file = new File(USERS_FILE);
|
||||
if (file.exists()) {
|
||||
File backup = new File(USERS_FILE + ".bak." + System.currentTimeMillis());
|
||||
file.renameTo(backup);
|
||||
System.err.println("损坏的文件已备份为: " + backup.getName());
|
||||
}
|
||||
saveUsers();
|
||||
System.out.println("已重新创建用户数据文件");
|
||||
} catch (Exception e) {
|
||||
System.err.println("备份文件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void saveUsers() {
|
||||
try {
|
||||
File file = new File(USERS_FILE);
|
||||
file.getParentFile().mkdirs();
|
||||
objectMapper.writerWithDefaultPrettyPrinter().writeValue(file, users.values().toArray(new User[0]));
|
||||
} catch (IOException e) {
|
||||
System.err.println("保存用户数据失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean registerUser(String email, String verificationCode) {
|
||||
if (users.containsKey(email)) {
|
||||
return false; // 用户已存在
|
||||
}
|
||||
|
||||
// 生成密码占位符,实际密码在验证后设置
|
||||
String tempPasswordHash = BCrypt.withDefaults().hashToString(12, "temp".toCharArray());
|
||||
User user = new User(email, tempPasswordHash, verificationCode);
|
||||
users.put(email, user);
|
||||
verificationCodeTimestamps.put(email, LocalDateTime.now());
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean verifyUser(String username, String email, String verificationCode, String password) {
|
||||
User user = users.get(email);
|
||||
if (user == null || !user.getVerificationCode().equals(verificationCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查验证码是否过期
|
||||
LocalDateTime codeTime = verificationCodeTimestamps.get(email);
|
||||
if (codeTime == null || codeTime.plusMinutes(VERIFICATION_CODE_EXPIRY_MINUTES).isBefore(LocalDateTime.now())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证密码格式
|
||||
if (!validatePassword(password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置实际密码
|
||||
String passwordHash = BCrypt.withDefaults().hashToString(12, password.toCharArray());
|
||||
user.setPasswordHash(passwordHash);
|
||||
user.setUsername(username);
|
||||
user.setVerified(true);
|
||||
verificationCodeTimestamps.remove(email);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean login(String email, String password) {
|
||||
User user = users.get(email);
|
||||
if (user == null || !user.isVerified()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BCrypt.Result result = BCrypt.verifyer().verify(password.toCharArray(), user.getPasswordHash());
|
||||
return result.verified;
|
||||
}
|
||||
|
||||
public int changePassword(String email, String oldPassword, String newPassword) {
|
||||
User user = users.get(email);
|
||||
if (user == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 验证旧密码
|
||||
BCrypt.Result result = BCrypt.verifyer().verify(oldPassword.toCharArray(), user.getPasswordHash());
|
||||
if (!result.verified) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// 验证新密码格式
|
||||
if (!validatePassword(newPassword)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (oldPassword.equals(newPassword)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
String newPasswordHash = BCrypt.withDefaults().hashToString(12, newPassword.toCharArray());
|
||||
user.setPasswordHash(newPasswordHash);
|
||||
saveUsers();
|
||||
return 5;
|
||||
}
|
||||
|
||||
public boolean setPasswordResetCode(String email, String verificationCode) {
|
||||
User user = users.get(email);
|
||||
if (user == null) {
|
||||
return false; // 用户不存在
|
||||
}
|
||||
|
||||
user.setVerificationCode(verificationCode);
|
||||
verificationCodeTimestamps.put(email, LocalDateTime.now());
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean resetPasswordWithCode(String email, String verificationCode, String newPassword) {
|
||||
User user = users.get(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证验证码
|
||||
if (!user.getVerificationCode().equals(verificationCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查验证码是否过期
|
||||
LocalDateTime codeTime = verificationCodeTimestamps.get(email);
|
||||
if (codeTime == null || codeTime.plusMinutes(VERIFICATION_CODE_EXPIRY_MINUTES).isBefore(LocalDateTime.now())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证新密码格式
|
||||
if (!validatePassword(newPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
String newPasswordHash = BCrypt.withDefaults().hashToString(12, newPassword.toCharArray());
|
||||
user.setPasswordHash(newPasswordHash);
|
||||
verificationCodeTimestamps.remove(email); // 清除验证码
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean updateUserType(String email, String type) {
|
||||
User user = users.get(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
user.setType(type);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean validatePassword(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 boolean userExists(String email) {
|
||||
return users.containsKey(email);
|
||||
}
|
||||
|
||||
public boolean isUserExistsAndVerified(String email) {
|
||||
User user = users.get(email);
|
||||
return user != null && user.isVerified();
|
||||
}
|
||||
|
||||
public boolean updateUsername(String email, String newUsername) {
|
||||
User user = users.get(email);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
user.setUsername(newUsername);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isValidEmail(String email) {
|
||||
return email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
|
||||
}
|
||||
|
||||
public User getUser(String email ) {
|
||||
User user = users.get(email);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@ -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