Compare commits
4 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
0464ec4599 | 3 months ago |
|
|
192a32695e | 3 months ago |
|
|
bdfb3f0be7 | 3 months ago |
|
|
c93b6e59c6 | 3 months ago |
@ -0,0 +1,172 @@
|
||||
package mathquiz.backend;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Email Service Class - Handles email verification code sending
|
||||
*/
|
||||
public class EmailService {
|
||||
|
||||
// Email configuration - loaded from properties file
|
||||
private String smtpHost;
|
||||
private String smtpPort;
|
||||
private String emailUsername;
|
||||
private String emailPassword;
|
||||
private String fromEmail;
|
||||
|
||||
public EmailService() {
|
||||
loadEmailConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load email configuration from properties file
|
||||
*/
|
||||
private void loadEmailConfig() {
|
||||
Properties config = new Properties();
|
||||
try {
|
||||
config.load(new FileInputStream("email_config.properties"));
|
||||
smtpHost = config.getProperty("smtp.host", "smtp.gmail.com");
|
||||
smtpPort = config.getProperty("smtp.port", "587");
|
||||
emailUsername = config.getProperty("email.username", "your-email@gmail.com");
|
||||
emailPassword = config.getProperty("email.password", "your-app-password");
|
||||
fromEmail = config.getProperty("email.from", "your-email@gmail.com");
|
||||
} catch (IOException e) {
|
||||
System.err.println("Warning: Could not load email configuration, using default settings");
|
||||
// Use default settings
|
||||
smtpHost = "smtp.gmail.com";
|
||||
smtpPort = "587";
|
||||
emailUsername = "your-email@gmail.com";
|
||||
emailPassword = "your-app-password";
|
||||
fromEmail = "your-email@gmail.com";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send verification code to email
|
||||
*/
|
||||
public String sendVerificationCode(String email) throws Exception {
|
||||
// Generate 6-digit numeric verification code
|
||||
String verificationCode = generateVerificationCode();
|
||||
|
||||
// Send real email
|
||||
sendRealEmail(email, verificationCode);
|
||||
|
||||
// Also save to file for backup verification
|
||||
saveVerificationCodeToFile(email, verificationCode);
|
||||
|
||||
return verificationCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate verification code
|
||||
*/
|
||||
private String generateVerificationCode() {
|
||||
Random random = new Random();
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
code.append(random.nextInt(10));
|
||||
}
|
||||
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send real email using SMTP protocol
|
||||
*/
|
||||
private void sendRealEmail(String email, String verificationCode) throws Exception {
|
||||
try {
|
||||
// Create email content
|
||||
String subject = "Math Quiz System - Registration Verification Code";
|
||||
String content = createEmailContent(verificationCode);
|
||||
|
||||
// Use SimpleEmailSender
|
||||
SimpleEmailSender sender = new SimpleEmailSender(
|
||||
smtpHost,
|
||||
Integer.parseInt(smtpPort),
|
||||
emailUsername,
|
||||
emailPassword,
|
||||
fromEmail
|
||||
);
|
||||
|
||||
sender.sendEmail(email, subject, content);
|
||||
|
||||
System.out.println("Verification code sent successfully to: " + email);
|
||||
System.out.println("Verification code: " + verificationCode);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to send email: " + e.getMessage());
|
||||
// Fall back to console output
|
||||
System.out.println("=== EMAIL VERIFICATION CODE ===");
|
||||
System.out.println("To: " + email);
|
||||
System.out.println("Subject: Math Quiz System - Registration Verification Code");
|
||||
System.out.println("Verification Code: " + verificationCode);
|
||||
System.out.println("Please check your email or use the code above.");
|
||||
System.out.println("================================");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create email content with HTML formatting
|
||||
*/
|
||||
private String createEmailContent(String verificationCode) {
|
||||
return "<html>" +
|
||||
"<head><meta charset='UTF-8'></head>" +
|
||||
"<body style='font-family: Arial, sans-serif; line-height: 1.6; color: #333;'>" +
|
||||
"<div style='max-width: 600px; margin: 0 auto; padding: 20px;'>" +
|
||||
"<h2 style='color: #0066cc; text-align: center;'>Math Quiz System</h2>" +
|
||||
"<h3 style='color: #333;'>Registration Verification</h3>" +
|
||||
"<p>Hello,</p>" +
|
||||
"<p>Thank you for registering with Math Quiz System. Please use the following verification code to complete your registration:</p>" +
|
||||
"<div style='background-color: #f0f8ff; border: 2px solid #0066cc; border-radius: 8px; padding: 20px; text-align: center; margin: 20px 0;'>" +
|
||||
"<h1 style='color: #0066cc; font-size: 32px; margin: 0; letter-spacing: 5px;'>" + verificationCode + "</h1>" +
|
||||
"</div>" +
|
||||
"<p><strong>Important:</strong></p>" +
|
||||
"<ul>" +
|
||||
"<li>This verification code will expire in 5 minutes</li>" +
|
||||
"<li>Please enter this code exactly as shown</li>" +
|
||||
"<li>If you did not request this code, please ignore this email</li>" +
|
||||
"</ul>" +
|
||||
"<p>Best regards,<br>Math Quiz System Team</p>" +
|
||||
"<hr style='border: none; border-top: 1px solid #eee; margin: 20px 0;'>" +
|
||||
"<p style='font-size: 12px; color: #666; text-align: center;'>This is an automated message, please do not reply.</p>" +
|
||||
"</div>" +
|
||||
"</body>" +
|
||||
"</html>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Save verification code to file (for demonstration only)
|
||||
*/
|
||||
private void saveVerificationCodeToFile(String email, String verificationCode) {
|
||||
try {
|
||||
java.nio.file.Files.createDirectories(java.nio.file.Paths.get("data"));
|
||||
java.nio.file.Files.write(
|
||||
java.nio.file.Paths.get("data/verification_codes.txt"),
|
||||
(email + ":" + verificationCode + "\n").getBytes(),
|
||||
java.nio.file.StandardOpenOption.CREATE,
|
||||
java.nio.file.StandardOpenOption.APPEND
|
||||
);
|
||||
} catch (Exception e) {
|
||||
// Ignore file save errors
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate email format
|
||||
*/
|
||||
public boolean isValidEmail(String email) {
|
||||
if (email == null || email.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String trimmedEmail = email.trim();
|
||||
return trimmedEmail.contains("@") &&
|
||||
trimmedEmail.contains(".") &&
|
||||
trimmedEmail.length() > 5;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package mathquiz.backend;
|
||||
|
||||
/**
|
||||
* Question Class - Represents a multiple choice question
|
||||
*/
|
||||
public class Question {
|
||||
private final String question;
|
||||
private final String optionA;
|
||||
private final String optionB;
|
||||
private final String optionC;
|
||||
private final String optionD;
|
||||
private final String correctAnswer;
|
||||
|
||||
public Question(String question, String optionA, String optionB, String optionC, String optionD, String correctAnswer) {
|
||||
this.question = question;
|
||||
this.optionA = optionA;
|
||||
this.optionB = optionB;
|
||||
this.optionC = optionC;
|
||||
this.optionD = optionD;
|
||||
this.correctAnswer = correctAnswer;
|
||||
}
|
||||
|
||||
public String getQuestion() {
|
||||
return question;
|
||||
}
|
||||
|
||||
public String getOptionA() {
|
||||
return optionA;
|
||||
}
|
||||
|
||||
public String getOptionB() {
|
||||
return optionB;
|
||||
}
|
||||
|
||||
public String getOptionC() {
|
||||
return optionC;
|
||||
}
|
||||
|
||||
public String getOptionD() {
|
||||
return optionD;
|
||||
}
|
||||
|
||||
public String getCorrectAnswer() {
|
||||
return correctAnswer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Question{" +
|
||||
"question='" + question + '\'' +
|
||||
", optionA='" + optionA + '\'' +
|
||||
", optionB='" + optionB + '\'' +
|
||||
", optionC='" + optionC + '\'' +
|
||||
", optionD='" + optionD + '\'' +
|
||||
", correctAnswer='" + correctAnswer + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,184 @@
|
||||
package mathquiz.backend;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import javax.net.ssl.*;
|
||||
|
||||
/**
|
||||
* Simple Email Sender using SMTP protocol
|
||||
* This class provides a basic SMTP client implementation
|
||||
*/
|
||||
public class SimpleEmailSender {
|
||||
|
||||
private String smtpHost;
|
||||
private int smtpPort;
|
||||
private String username;
|
||||
private String password;
|
||||
private String fromEmail;
|
||||
|
||||
public SimpleEmailSender(String smtpHost, int smtpPort, String username, String password, String fromEmail) {
|
||||
this.smtpHost = smtpHost;
|
||||
this.smtpPort = smtpPort;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.fromEmail = fromEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email using SMTP protocol with SSL/TLS support
|
||||
*/
|
||||
public void sendEmail(String toEmail, String subject, String content) throws Exception {
|
||||
Socket socket = null;
|
||||
BufferedReader reader = null;
|
||||
PrintWriter writer = null;
|
||||
|
||||
try {
|
||||
System.out.println("Connecting to SMTP server: " + smtpHost + ":" + smtpPort);
|
||||
|
||||
// Connect to SMTP server
|
||||
socket = new Socket(smtpHost, smtpPort);
|
||||
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
writer = new PrintWriter(socket.getOutputStream(), true);
|
||||
|
||||
// Read server greeting
|
||||
String response = reader.readLine();
|
||||
System.out.println("Server greeting: " + response);
|
||||
if (!response.startsWith("220")) {
|
||||
throw new Exception("SMTP server error: " + response);
|
||||
}
|
||||
|
||||
// Send EHLO command
|
||||
String hostname = InetAddress.getLocalHost().getHostName();
|
||||
if (hostname == null || hostname.isEmpty()) {
|
||||
hostname = "localhost";
|
||||
}
|
||||
writer.println("EHLO " + hostname);
|
||||
response = reader.readLine();
|
||||
System.out.println("EHLO response: " + response);
|
||||
if (!response.startsWith("250")) {
|
||||
throw new Exception("EHLO failed: " + response);
|
||||
}
|
||||
|
||||
// Read additional EHLO responses
|
||||
while (response.startsWith("250-")) {
|
||||
response = reader.readLine();
|
||||
System.out.println("EHLO continuation: " + response);
|
||||
}
|
||||
|
||||
// Start TLS if supported
|
||||
writer.println("STARTTLS");
|
||||
response = reader.readLine();
|
||||
System.out.println("STARTTLS response: " + response);
|
||||
if (response.startsWith("220")) {
|
||||
// Upgrade to SSL socket
|
||||
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||
SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, smtpHost, smtpPort, true);
|
||||
sslSocket.startHandshake();
|
||||
|
||||
// Update streams to use SSL socket
|
||||
reader = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
|
||||
writer = new PrintWriter(sslSocket.getOutputStream(), true);
|
||||
|
||||
// Send EHLO again after TLS
|
||||
writer.println("EHLO " + hostname);
|
||||
response = reader.readLine();
|
||||
System.out.println("EHLO after TLS: " + response);
|
||||
if (!response.startsWith("250")) {
|
||||
throw new Exception("EHLO after TLS failed: " + response);
|
||||
}
|
||||
|
||||
// Read additional EHLO responses
|
||||
while (response.startsWith("250-")) {
|
||||
response = reader.readLine();
|
||||
System.out.println("EHLO continuation after TLS: " + response);
|
||||
}
|
||||
}
|
||||
|
||||
// Authenticate using AUTH LOGIN
|
||||
writer.println("AUTH LOGIN");
|
||||
response = reader.readLine();
|
||||
System.out.println("AUTH LOGIN response: " + response);
|
||||
if (!response.startsWith("334")) {
|
||||
throw new Exception("AUTH LOGIN failed: " + response);
|
||||
}
|
||||
|
||||
// Send username (base64 encoded)
|
||||
String encodedUsername = java.util.Base64.getEncoder().encodeToString(username.getBytes());
|
||||
writer.println(encodedUsername);
|
||||
response = reader.readLine();
|
||||
System.out.println("Username auth response: " + response);
|
||||
if (!response.startsWith("334")) {
|
||||
throw new Exception("Username authentication failed: " + response);
|
||||
}
|
||||
|
||||
// Send password (base64 encoded)
|
||||
String encodedPassword = java.util.Base64.getEncoder().encodeToString(password.getBytes());
|
||||
writer.println(encodedPassword);
|
||||
response = reader.readLine();
|
||||
System.out.println("Password auth response: " + response);
|
||||
if (!response.startsWith("235")) {
|
||||
throw new Exception("Password authentication failed: " + response);
|
||||
}
|
||||
|
||||
// Send MAIL FROM
|
||||
writer.println("MAIL FROM:<" + fromEmail + ">");
|
||||
response = reader.readLine();
|
||||
System.out.println("MAIL FROM response: " + response);
|
||||
if (!response.startsWith("250")) {
|
||||
throw new Exception("MAIL FROM failed: " + response);
|
||||
}
|
||||
|
||||
// Send RCPT TO
|
||||
writer.println("RCPT TO:<" + toEmail + ">");
|
||||
response = reader.readLine();
|
||||
System.out.println("RCPT TO response: " + response);
|
||||
if (!response.startsWith("250")) {
|
||||
throw new Exception("RCPT TO failed: " + response);
|
||||
}
|
||||
|
||||
// Send DATA
|
||||
writer.println("DATA");
|
||||
response = reader.readLine();
|
||||
System.out.println("DATA response: " + response);
|
||||
if (!response.startsWith("354")) {
|
||||
throw new Exception("DATA failed: " + response);
|
||||
}
|
||||
|
||||
// Send email headers and content
|
||||
writer.println("From: " + fromEmail);
|
||||
writer.println("To: " + toEmail);
|
||||
writer.println("Subject: " + subject);
|
||||
writer.println("MIME-Version: 1.0");
|
||||
writer.println("Content-Type: text/html; charset=UTF-8");
|
||||
writer.println();
|
||||
writer.println(content);
|
||||
writer.println(".");
|
||||
|
||||
response = reader.readLine();
|
||||
System.out.println("Email send response: " + response);
|
||||
if (!response.startsWith("250")) {
|
||||
throw new Exception("Email sending failed: " + response);
|
||||
}
|
||||
|
||||
// Quit
|
||||
writer.println("QUIT");
|
||||
response = reader.readLine();
|
||||
System.out.println("QUIT response: " + response);
|
||||
|
||||
System.out.println("Email sent successfully to: " + toEmail);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to send email: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} finally {
|
||||
try {
|
||||
if (writer != null) writer.close();
|
||||
if (reader != null) reader.close();
|
||||
if (socket != null) socket.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,209 @@
|
||||
package mathquiz.backend;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* User Service Class - Handles user registration, login, password management
|
||||
*/
|
||||
public class UserService {
|
||||
private static final String USERS_FILE = "data/users.txt";
|
||||
private static final String PASSWORDS_FILE = "data/passwords.txt";
|
||||
|
||||
private Map<String, String> userPasswords;
|
||||
private Map<String, String> userEmails;
|
||||
|
||||
public UserService() {
|
||||
loadUserData();
|
||||
}
|
||||
|
||||
/**
|
||||
* User registration
|
||||
*/
|
||||
public void registerUser(String email, String username) throws IOException {
|
||||
if (userEmails.containsValue(email)) {
|
||||
throw new IllegalArgumentException("This email has already been registered");
|
||||
}
|
||||
|
||||
userEmails.put(username, email);
|
||||
|
||||
// Save user data
|
||||
saveUserData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set password
|
||||
*/
|
||||
public void setPassword(String email, String password) throws IOException {
|
||||
if (!isValidPassword(password)) {
|
||||
throw new IllegalArgumentException("Password does not meet requirements");
|
||||
}
|
||||
|
||||
String username = getUsernameByEmail(email);
|
||||
if (username == null) {
|
||||
throw new IllegalArgumentException("User does not exist");
|
||||
}
|
||||
|
||||
userPasswords.put(username, password);
|
||||
savePasswordData();
|
||||
}
|
||||
|
||||
/**
|
||||
* User login
|
||||
*/
|
||||
public boolean login(String email, String password) {
|
||||
String username = getUsernameByEmail(email);
|
||||
if (username == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String storedPassword = userPasswords.get(username);
|
||||
if (storedPassword == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Objects.equals(storedPassword, password)) {
|
||||
// Set current user (use email for session)
|
||||
mathquiz.gui.QuizSession.getInstance().setCurrentUser(email);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change password
|
||||
*/
|
||||
public boolean changePassword(String username, String oldPassword, String newPassword) throws IOException {
|
||||
if (!isValidPassword(newPassword)) {
|
||||
throw new IllegalArgumentException("New password does not meet requirements");
|
||||
}
|
||||
|
||||
String storedPassword = userPasswords.get(username);
|
||||
if (!Objects.equals(storedPassword, oldPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
userPasswords.put(username, newPassword);
|
||||
savePasswordData();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate password format
|
||||
*/
|
||||
private boolean isValidPassword(String password) {
|
||||
if (password.length() < 6 || password.length() > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasUpperCase = false;
|
||||
boolean hasLowerCase = false;
|
||||
boolean hasDigit = false;
|
||||
|
||||
for (char c : password.toCharArray()) {
|
||||
if (Character.isUpperCase(c)) {
|
||||
hasUpperCase = true;
|
||||
} else if (Character.isLowerCase(c)) {
|
||||
hasLowerCase = true;
|
||||
} else if (Character.isDigit(c)) {
|
||||
hasDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasUpperCase && hasLowerCase && hasDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get username by email
|
||||
*/
|
||||
private String getUsernameByEmail(String email) {
|
||||
for (Map.Entry<String, String> entry : userEmails.entrySet()) {
|
||||
if (entry.getValue().equals(email)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate username
|
||||
*/
|
||||
private String generateUsername(String email) {
|
||||
String baseName = email.split("@")[0];
|
||||
String username = baseName;
|
||||
int counter = 1;
|
||||
|
||||
while (userEmails.containsKey(username)) {
|
||||
username = baseName + counter;
|
||||
counter++;
|
||||
}
|
||||
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user data
|
||||
*/
|
||||
private void loadUserData() {
|
||||
userPasswords = new HashMap<>();
|
||||
userEmails = new HashMap<>();
|
||||
|
||||
try {
|
||||
// Create data directory
|
||||
Files.createDirectories(Paths.get("data"));
|
||||
|
||||
// Load user email mapping
|
||||
if (Files.exists(Paths.get(USERS_FILE))) {
|
||||
for (String line : Files.readAllLines(Paths.get(USERS_FILE))) {
|
||||
String[] parts = line.split(",");
|
||||
if (parts.length == 2) {
|
||||
userEmails.put(parts[0], parts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load user passwords
|
||||
if (Files.exists(Paths.get(PASSWORDS_FILE))) {
|
||||
for (String line : Files.readAllLines(Paths.get(PASSWORDS_FILE))) {
|
||||
String[] parts = line.split(",");
|
||||
if (parts.length == 2) {
|
||||
userPasswords.put(parts[0], parts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// If loading fails, use empty data
|
||||
userPasswords = new HashMap<>();
|
||||
userEmails = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save user data
|
||||
*/
|
||||
private void saveUserData() throws IOException {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(USERS_FILE))) {
|
||||
for (Map.Entry<String, String> entry : userEmails.entrySet()) {
|
||||
writer.write(entry.getKey() + "," + entry.getValue());
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save password data
|
||||
*/
|
||||
private void savePasswordData() throws IOException {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(PASSWORDS_FILE))) {
|
||||
for (Map.Entry<String, String> entry : userPasswords.entrySet()) {
|
||||
writer.write(entry.getKey() + "," + entry.getValue());
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,186 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import mathquiz.backend.UserService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Change Password Dialog
|
||||
*/
|
||||
public class ChangePasswordDialog extends JDialog {
|
||||
private JPasswordField newPasswordField;
|
||||
private JPasswordField confirmPasswordField;
|
||||
private JButton okButton;
|
||||
private JButton cancelButton;
|
||||
private JLabel messageLabel;
|
||||
|
||||
public ChangePasswordDialog(JFrame parent) {
|
||||
super(parent, "Change Password", true);
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
setLocationRelativeTo(parent);
|
||||
setSize(400, 300);
|
||||
setResizable(false);
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
newPasswordField = new JPasswordField(20);
|
||||
confirmPasswordField = new JPasswordField(20);
|
||||
okButton = new JButton("OK");
|
||||
cancelButton = new JButton("Cancel");
|
||||
messageLabel = new JLabel("", JLabel.CENTER);
|
||||
|
||||
messageLabel.setForeground(Color.RED);
|
||||
okButton.setPreferredSize(new Dimension(80, 30));
|
||||
cancelButton.setPreferredSize(new Dimension(80, 30));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Input panel
|
||||
JPanel inputPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(10, 10, 10, 10);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 0;
|
||||
inputPanel.add(new JLabel("New Password:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(newPasswordField, gbc);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 1;
|
||||
inputPanel.add(new JLabel("Confirm Password:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(confirmPasswordField, gbc);
|
||||
|
||||
// Password requirement description
|
||||
JPanel requirementPanel = new JPanel();
|
||||
JLabel requirementLabel = new JLabel("<html>Password requirements: 6-10 characters, must include uppercase, lowercase and digits</html>");
|
||||
requirementLabel.setForeground(Color.BLUE);
|
||||
requirementLabel.setFont(new Font("Arial", Font.PLAIN, 12));
|
||||
requirementPanel.add(requirementLabel);
|
||||
|
||||
// Button panel
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(okButton);
|
||||
buttonPanel.add(cancelButton);
|
||||
|
||||
// Message panel
|
||||
JPanel messagePanel = new JPanel();
|
||||
messagePanel.add(messageLabel);
|
||||
|
||||
// Create main content panel
|
||||
JPanel mainContentPanel = new JPanel();
|
||||
mainContentPanel.setLayout(new BoxLayout(mainContentPanel, BoxLayout.Y_AXIS));
|
||||
mainContentPanel.add(inputPanel);
|
||||
mainContentPanel.add(requirementPanel);
|
||||
|
||||
// Create bottom panel with buttons and message
|
||||
JPanel bottomPanel = new JPanel();
|
||||
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
|
||||
bottomPanel.add(buttonPanel);
|
||||
bottomPanel.add(messagePanel);
|
||||
|
||||
// Assemble
|
||||
add(mainContentPanel, BorderLayout.CENTER);
|
||||
add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
setSize(400, 300);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
changePassword();
|
||||
}
|
||||
});
|
||||
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
|
||||
// Enter key handling
|
||||
confirmPasswordField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
changePassword();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changePassword() {
|
||||
String newPassword = new String(newPasswordField.getPassword());
|
||||
String confirmPassword = new String(confirmPasswordField.getPassword());
|
||||
|
||||
if (newPassword.isEmpty() || confirmPassword.isEmpty()) {
|
||||
showMessage("Please fill in all fields", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newPassword.equals(confirmPassword)) {
|
||||
showMessage("New passwords do not match", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidPassword(newPassword)) {
|
||||
showMessage("New password does not meet requirements: 6-10 characters, must include uppercase, lowercase and digits", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
UserService userService = new UserService();
|
||||
String currentUser = mathquiz.gui.QuizSession.getInstance().getCurrentUser();
|
||||
|
||||
userService.setPassword(currentUser, newPassword);
|
||||
showMessage("Password changed successfully", Color.GREEN);
|
||||
|
||||
// Close dialog after delay
|
||||
Timer timer = new Timer(1000, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
timer.setRepeats(false);
|
||||
timer.start();
|
||||
|
||||
} catch (Exception ex) {
|
||||
showMessage("Password change failed: " + ex.getMessage(), Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidPassword(String password) {
|
||||
if (password.length() < 6 || password.length() > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasUpperCase = false;
|
||||
boolean hasLowerCase = false;
|
||||
boolean hasDigit = false;
|
||||
|
||||
for (char c : password.toCharArray()) {
|
||||
if (Character.isUpperCase(c)) {
|
||||
hasUpperCase = true;
|
||||
} else if (Character.isLowerCase(c)) {
|
||||
hasLowerCase = true;
|
||||
} else if (Character.isDigit(c)) {
|
||||
hasDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasUpperCase && hasLowerCase && hasDigit;
|
||||
}
|
||||
|
||||
private void showMessage(String message, Color color) {
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import mathquiz.AccountType;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Grade Selection Panel
|
||||
*/
|
||||
public class GradeSelectionPanel extends JPanel {
|
||||
private final MainFrame mainFrame;
|
||||
private JButton primaryButton;
|
||||
private JButton middleButton;
|
||||
private JButton highButton;
|
||||
private JButton logoutButton;
|
||||
private JButton changePasswordButton;
|
||||
private JLabel messageLabel;
|
||||
|
||||
public GradeSelectionPanel(MainFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
primaryButton = new JButton("Primary School");
|
||||
middleButton = new JButton("Middle School");
|
||||
highButton = new JButton("High School");
|
||||
logoutButton = new JButton("Logout");
|
||||
changePasswordButton = new JButton("Change Password");
|
||||
messageLabel = new JLabel("Please select your grade level", JLabel.CENTER);
|
||||
|
||||
messageLabel.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
messageLabel.setForeground(Color.BLUE);
|
||||
|
||||
// Set button styles
|
||||
primaryButton.setPreferredSize(new Dimension(150, 60));
|
||||
middleButton.setPreferredSize(new Dimension(150, 60));
|
||||
highButton.setPreferredSize(new Dimension(150, 60));
|
||||
logoutButton.setPreferredSize(new Dimension(120, 40));
|
||||
changePasswordButton.setPreferredSize(new Dimension(150, 40));
|
||||
|
||||
primaryButton.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
middleButton.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
highButton.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
|
||||
// Title
|
||||
JPanel titlePanel = new JPanel();
|
||||
JLabel titleLabel = new JLabel("Math Quiz System", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
// Message panel
|
||||
JPanel messagePanel = new JPanel();
|
||||
messagePanel.add(messageLabel);
|
||||
|
||||
// Grade selection panel
|
||||
JPanel gradePanel = new JPanel(new GridLayout(1, 3, 20, 20));
|
||||
gradePanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
gradePanel.add(primaryButton);
|
||||
gradePanel.add(middleButton);
|
||||
gradePanel.add(highButton);
|
||||
|
||||
// Bottom button panel
|
||||
JPanel bottomPanel = new JPanel(new FlowLayout());
|
||||
bottomPanel.add(changePasswordButton);
|
||||
bottomPanel.add(logoutButton);
|
||||
|
||||
// Assemble
|
||||
mainPanel.add(titlePanel, BorderLayout.NORTH);
|
||||
mainPanel.add(messagePanel, BorderLayout.NORTH);
|
||||
mainPanel.add(gradePanel, BorderLayout.CENTER);
|
||||
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
primaryButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
selectGrade(AccountType.PRIMARY);
|
||||
}
|
||||
});
|
||||
|
||||
middleButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
selectGrade(AccountType.MIDDLE);
|
||||
}
|
||||
});
|
||||
|
||||
highButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
selectGrade(AccountType.HIGH);
|
||||
}
|
||||
});
|
||||
|
||||
changePasswordButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
changePassword();
|
||||
}
|
||||
});
|
||||
|
||||
logoutButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
logout();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void selectGrade(AccountType grade) {
|
||||
// Save selected grade to global state
|
||||
QuizSession.getInstance().setAccountType(grade);
|
||||
showMessage("Selected " + grade.displayName() + " grade", Color.GREEN);
|
||||
|
||||
// Jump to question count input interface
|
||||
mainFrame.showQuestionCountPanel();
|
||||
}
|
||||
|
||||
private void changePassword() {
|
||||
// Show change password dialog
|
||||
ChangePasswordDialog dialog = new ChangePasswordDialog(mainFrame);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private void logout() {
|
||||
// Clear session information
|
||||
QuizSession.getInstance().clear();
|
||||
|
||||
// Return to login interface
|
||||
mainFrame.showLoginPanel();
|
||||
}
|
||||
|
||||
private void showMessage(String message, Color color) {
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,196 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import mathquiz.backend.UserService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Login Panel
|
||||
*/
|
||||
public class LoginPanel extends JPanel {
|
||||
private final MainFrame mainFrame;
|
||||
private JTextField usernameField;
|
||||
private JTextField emailField;
|
||||
private JPasswordField passwordField;
|
||||
private JButton loginButton;
|
||||
private JButton registerButton;
|
||||
private JLabel messageLabel;
|
||||
|
||||
public LoginPanel(MainFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
// Create components
|
||||
usernameField = new JTextField(20);
|
||||
emailField = new JTextField(20);
|
||||
passwordField = new JPasswordField(20);
|
||||
loginButton = new JButton("Login");
|
||||
registerButton = new JButton("Register");
|
||||
messageLabel = new JLabel("", JLabel.CENTER);
|
||||
|
||||
messageLabel.setForeground(Color.RED);
|
||||
|
||||
// Set component styles
|
||||
loginButton.setPreferredSize(new Dimension(100, 35));
|
||||
registerButton.setPreferredSize(new Dimension(100, 35));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Title panel
|
||||
JPanel titlePanel = new JPanel();
|
||||
JLabel titleLabel = new JLabel("Math Quiz System", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 28));
|
||||
titleLabel.setForeground(new Color(0, 102, 204));
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
// Main content panel with centered layout
|
||||
JPanel contentPanel = new JPanel(new GridBagLayout());
|
||||
contentPanel.setBackground(new Color(248, 249, 250));
|
||||
contentPanel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
|
||||
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(15, 15, 15, 15);
|
||||
|
||||
// Username input with centered alignment
|
||||
gbc.gridx = 0; gbc.gridy = 0;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
JLabel usernameLabel = new JLabel("Username:");
|
||||
usernameLabel.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
contentPanel.add(usernameLabel, gbc);
|
||||
|
||||
gbc.gridx = 1; gbc.gridy = 0;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
usernameField.setPreferredSize(new Dimension(200, 30));
|
||||
usernameField.setFont(new Font("Arial", Font.PLAIN, 14));
|
||||
contentPanel.add(usernameField, gbc);
|
||||
|
||||
// Email input with centered alignment
|
||||
gbc.gridx = 0; gbc.gridy = 1;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
JLabel emailLabel = new JLabel("Email:");
|
||||
emailLabel.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
contentPanel.add(emailLabel, gbc);
|
||||
|
||||
gbc.gridx = 1; gbc.gridy = 1;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
emailField.setPreferredSize(new Dimension(200, 30));
|
||||
emailField.setFont(new Font("Arial", Font.PLAIN, 14));
|
||||
contentPanel.add(emailField, gbc);
|
||||
|
||||
// Password input with centered alignment
|
||||
gbc.gridx = 0; gbc.gridy = 2;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
JLabel passwordLabel = new JLabel("Password:");
|
||||
passwordLabel.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
contentPanel.add(passwordLabel, gbc);
|
||||
|
||||
gbc.gridx = 1; gbc.gridy = 2;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
passwordField.setPreferredSize(new Dimension(200, 30));
|
||||
passwordField.setFont(new Font("Arial", Font.PLAIN, 14));
|
||||
contentPanel.add(passwordField, gbc);
|
||||
|
||||
// Buttons panel with centered alignment
|
||||
gbc.gridx = 0; gbc.gridy = 3;
|
||||
gbc.gridwidth = 2;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.setOpaque(false);
|
||||
buttonPanel.add(loginButton);
|
||||
buttonPanel.add(registerButton);
|
||||
contentPanel.add(buttonPanel, gbc);
|
||||
|
||||
// Message panel
|
||||
gbc.gridx = 0; gbc.gridy = 4;
|
||||
gbc.gridwidth = 2;
|
||||
JPanel messagePanel = new JPanel();
|
||||
messagePanel.setOpaque(false);
|
||||
messagePanel.add(messageLabel);
|
||||
contentPanel.add(messagePanel, gbc);
|
||||
|
||||
// Assemble main panel
|
||||
add(titlePanel, BorderLayout.NORTH);
|
||||
add(contentPanel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
loginButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
performLogin();
|
||||
}
|
||||
});
|
||||
|
||||
registerButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showRegisterPanel();
|
||||
}
|
||||
});
|
||||
|
||||
// Enter key login
|
||||
passwordField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
performLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void performLogin() {
|
||||
String username = usernameField.getText().trim();
|
||||
String email = emailField.getText().trim();
|
||||
String password = new String(passwordField.getPassword());
|
||||
|
||||
if (username.isEmpty() || email.isEmpty() || password.isEmpty()) {
|
||||
showMessage("Please enter username, email and password", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidEmail(email)) {
|
||||
showMessage("Please enter a valid email address", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
UserService userService = new UserService();
|
||||
if (userService.login(email, password)) {
|
||||
// Set current user in session
|
||||
QuizSession.getInstance().setCurrentUser(email);
|
||||
showMessage("Login successful", Color.GREEN);
|
||||
mainFrame.showGradeSelectionPanel();
|
||||
} else {
|
||||
showMessage("Email or password is incorrect", Color.RED);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
showMessage("Login failed: " + ex.getMessage(), Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidEmail(String email) {
|
||||
return email.contains("@") && email.contains(".");
|
||||
}
|
||||
|
||||
private void showMessage(String message, Color color) {
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
|
||||
public void clearFields() {
|
||||
emailField.setText("");
|
||||
passwordField.setText("");
|
||||
messageLabel.setText("");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Main Window Class - Math Quiz System GUI Main Interface
|
||||
*/
|
||||
public class MainFrame extends JFrame {
|
||||
private CardLayout cardLayout;
|
||||
private JPanel mainPanel;
|
||||
|
||||
// Various interface panels
|
||||
private LoginPanel loginPanel;
|
||||
private RegisterPanel registerPanel;
|
||||
private PasswordSetupPanel passwordSetupPanel;
|
||||
private GradeSelectionPanel gradeSelectionPanel;
|
||||
private QuestionCountPanel questionCountPanel;
|
||||
private QuizPanel quizPanel;
|
||||
private ResultPanel resultPanel;
|
||||
|
||||
public MainFrame() {
|
||||
initializeFrame();
|
||||
createPanels();
|
||||
setupLayout();
|
||||
showLoginPanel();
|
||||
}
|
||||
|
||||
private void initializeFrame() {
|
||||
setTitle("Math Quiz System");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(800, 600);
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(false);
|
||||
|
||||
// Set UTF-8 encoding
|
||||
System.setProperty("file.encoding", "UTF-8");
|
||||
}
|
||||
|
||||
private void createPanels() {
|
||||
cardLayout = new CardLayout();
|
||||
mainPanel = new JPanel(cardLayout);
|
||||
|
||||
// Create various panels
|
||||
loginPanel = new LoginPanel(this);
|
||||
registerPanel = new RegisterPanel(this);
|
||||
passwordSetupPanel = new PasswordSetupPanel(this);
|
||||
gradeSelectionPanel = new GradeSelectionPanel(this);
|
||||
questionCountPanel = new QuestionCountPanel(this);
|
||||
quizPanel = new QuizPanel(this);
|
||||
resultPanel = new ResultPanel(this);
|
||||
|
||||
// Add panels to main panel
|
||||
mainPanel.add(loginPanel, "LOGIN");
|
||||
mainPanel.add(registerPanel, "REGISTER");
|
||||
mainPanel.add(passwordSetupPanel, "PASSWORD_SETUP");
|
||||
mainPanel.add(gradeSelectionPanel, "GRADE_SELECTION");
|
||||
mainPanel.add(questionCountPanel, "QUESTION_COUNT");
|
||||
mainPanel.add(quizPanel, "QUIZ");
|
||||
mainPanel.add(resultPanel, "RESULT");
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
// Methods to show various panels
|
||||
public void showLoginPanel() {
|
||||
cardLayout.show(mainPanel, "LOGIN");
|
||||
}
|
||||
|
||||
public void showRegisterPanel() {
|
||||
cardLayout.show(mainPanel, "REGISTER");
|
||||
}
|
||||
|
||||
public void showPasswordSetupPanel(String email) {
|
||||
passwordSetupPanel.setEmail(email);
|
||||
cardLayout.show(mainPanel, "PASSWORD_SETUP");
|
||||
}
|
||||
|
||||
public void showGradeSelectionPanel() {
|
||||
cardLayout.show(mainPanel, "GRADE_SELECTION");
|
||||
}
|
||||
|
||||
public void showQuestionCountPanel() {
|
||||
questionCountPanel.updateGradeDisplay();
|
||||
cardLayout.show(mainPanel, "QUESTION_COUNT");
|
||||
}
|
||||
|
||||
public void showQuizPanel() {
|
||||
quizPanel.startQuiz();
|
||||
cardLayout.show(mainPanel, "QUIZ");
|
||||
}
|
||||
|
||||
public void showResultPanel(int score, int total) {
|
||||
resultPanel.setScore(score, total);
|
||||
cardLayout.show(mainPanel, "RESULT");
|
||||
}
|
||||
|
||||
// Get references to various panels for use by other panels
|
||||
public LoginPanel getLoginPanel() { return loginPanel; }
|
||||
public RegisterPanel getRegisterPanel() { return registerPanel; }
|
||||
public PasswordSetupPanel getPasswordSetupPanel() { return passwordSetupPanel; }
|
||||
public GradeSelectionPanel getGradeSelectionPanel() { return gradeSelectionPanel; }
|
||||
public QuestionCountPanel getQuestionCountPanel() { return questionCountPanel; }
|
||||
public QuizPanel getQuizPanel() { return quizPanel; }
|
||||
public ResultPanel getResultPanel() { return resultPanel; }
|
||||
}
|
||||
@ -0,0 +1,224 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import mathquiz.backend.UserService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Password Setup Panel
|
||||
*/
|
||||
public class PasswordSetupPanel extends JPanel {
|
||||
private final MainFrame mainFrame;
|
||||
private JPasswordField passwordField;
|
||||
private JPasswordField confirmPasswordField;
|
||||
private JButton setPasswordButton;
|
||||
private JButton backButton;
|
||||
private JLabel messageLabel;
|
||||
private JLabel emailLabel;
|
||||
|
||||
private String email;
|
||||
|
||||
public PasswordSetupPanel(MainFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
passwordField = new JPasswordField(20);
|
||||
confirmPasswordField = new JPasswordField(20);
|
||||
setPasswordButton = new JButton("Set Password");
|
||||
backButton = new JButton("Back");
|
||||
messageLabel = new JLabel("", JLabel.CENTER);
|
||||
emailLabel = new JLabel("", JLabel.CENTER);
|
||||
|
||||
messageLabel.setForeground(Color.RED);
|
||||
emailLabel.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
|
||||
setPasswordButton.setPreferredSize(new Dimension(120, 35));
|
||||
backButton.setPreferredSize(new Dimension(100, 35));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
|
||||
// Title
|
||||
JPanel titlePanel = new JPanel();
|
||||
JLabel titleLabel = new JLabel("Set Password", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
// Email display
|
||||
JPanel emailPanel = new JPanel();
|
||||
emailPanel.add(emailLabel);
|
||||
|
||||
// Input panel
|
||||
JPanel inputPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(10, 10, 10, 10);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 0;
|
||||
inputPanel.add(new JLabel("New Password:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(passwordField, gbc);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 1;
|
||||
inputPanel.add(new JLabel("Confirm Password:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(confirmPasswordField, gbc);
|
||||
|
||||
// Password requirement description
|
||||
JPanel requirementPanel = new JPanel();
|
||||
JLabel requirementLabel = new JLabel("<html>Password requirements: 6-10 characters, must include uppercase, lowercase and digits</html>");
|
||||
requirementLabel.setForeground(Color.BLUE);
|
||||
requirementPanel.add(requirementLabel);
|
||||
|
||||
// Button panel
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(setPasswordButton);
|
||||
buttonPanel.add(backButton);
|
||||
|
||||
// Message panel
|
||||
JPanel messagePanel = new JPanel();
|
||||
messagePanel.add(messageLabel);
|
||||
|
||||
// Create a proper layout structure
|
||||
JPanel container = new JPanel(new BorderLayout());
|
||||
|
||||
// Add title at top
|
||||
container.add(titlePanel, BorderLayout.NORTH);
|
||||
|
||||
// Create center panel with email, input, and requirements
|
||||
JPanel centerPanel = new JPanel();
|
||||
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
|
||||
centerPanel.add(emailPanel);
|
||||
centerPanel.add(inputPanel);
|
||||
centerPanel.add(requirementPanel);
|
||||
|
||||
// Add center panel to container
|
||||
container.add(centerPanel, BorderLayout.CENTER);
|
||||
|
||||
// Create bottom panel with buttons and message
|
||||
JPanel bottomPanel = new JPanel();
|
||||
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
|
||||
bottomPanel.add(buttonPanel);
|
||||
bottomPanel.add(messagePanel);
|
||||
|
||||
// Add bottom panel to container
|
||||
container.add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
add(container);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
setPasswordButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setPassword();
|
||||
}
|
||||
});
|
||||
|
||||
backButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showLoginPanel();
|
||||
}
|
||||
});
|
||||
|
||||
// Enter key handling
|
||||
confirmPasswordField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setPassword();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setPassword() {
|
||||
String password = new String(passwordField.getPassword());
|
||||
String confirmPassword = new String(confirmPasswordField.getPassword());
|
||||
|
||||
if (password.isEmpty() || confirmPassword.isEmpty()) {
|
||||
showMessage("Please enter password", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password.equals(confirmPassword)) {
|
||||
showMessage("Passwords do not match", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidPassword(password)) {
|
||||
showMessage("Password does not meet requirements: 6-10 characters, must include uppercase, lowercase and digits", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
UserService userService = new UserService();
|
||||
userService.setPassword(email, password);
|
||||
|
||||
// Set user session after successful password setup
|
||||
QuizSession.getInstance().setCurrentUser(email);
|
||||
|
||||
showMessage("Password set successfully!", Color.GREEN);
|
||||
|
||||
// Delay jump to grade selection interface
|
||||
Timer timer = new Timer(1000, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showGradeSelectionPanel();
|
||||
}
|
||||
});
|
||||
timer.setRepeats(false);
|
||||
timer.start();
|
||||
|
||||
} catch (Exception ex) {
|
||||
showMessage("Password setup failed: " + ex.getMessage(), Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidPassword(String password) {
|
||||
if (password.length() < 6 || password.length() > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasUpperCase = false;
|
||||
boolean hasLowerCase = false;
|
||||
boolean hasDigit = false;
|
||||
|
||||
for (char c : password.toCharArray()) {
|
||||
if (Character.isUpperCase(c)) {
|
||||
hasUpperCase = true;
|
||||
} else if (Character.isLowerCase(c)) {
|
||||
hasLowerCase = true;
|
||||
} else if (Character.isDigit(c)) {
|
||||
hasDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasUpperCase && hasLowerCase && hasDigit;
|
||||
}
|
||||
|
||||
private void showMessage(String message, Color color) {
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
emailLabel.setText("Set password for " + email);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
passwordField.setText("");
|
||||
confirmPasswordField.setText("");
|
||||
messageLabel.setText("");
|
||||
email = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Question Count Input Panel
|
||||
*/
|
||||
public class QuestionCountPanel extends JPanel {
|
||||
private final MainFrame mainFrame;
|
||||
private JTextField countField;
|
||||
private JButton startButton;
|
||||
private JButton backButton;
|
||||
private JLabel messageLabel;
|
||||
private JLabel gradeLabel;
|
||||
|
||||
public QuestionCountPanel(MainFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
countField = new JTextField(10);
|
||||
startButton = new JButton("Confirm & Start Quiz");
|
||||
backButton = new JButton("Back");
|
||||
messageLabel = new JLabel("", JLabel.CENTER);
|
||||
gradeLabel = new JLabel("", JLabel.CENTER);
|
||||
|
||||
messageLabel.setForeground(Color.RED);
|
||||
gradeLabel.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
gradeLabel.setForeground(Color.BLUE);
|
||||
|
||||
startButton.setPreferredSize(new Dimension(120, 35));
|
||||
backButton.setPreferredSize(new Dimension(100, 35));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
|
||||
// Title
|
||||
JPanel titlePanel = new JPanel();
|
||||
JLabel titleLabel = new JLabel("Set Question Count", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
// Grade display
|
||||
JPanel gradePanel = new JPanel();
|
||||
gradePanel.add(gradeLabel);
|
||||
|
||||
// Input panel
|
||||
JPanel inputPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(20, 10, 20, 10);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 0;
|
||||
inputPanel.add(new JLabel("Question Count (10-30):"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(countField, gbc);
|
||||
|
||||
// Button panel
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(startButton);
|
||||
buttonPanel.add(backButton);
|
||||
|
||||
// Message panel
|
||||
JPanel messagePanel = new JPanel();
|
||||
messagePanel.add(messageLabel);
|
||||
|
||||
// Assemble
|
||||
mainPanel.add(titlePanel, BorderLayout.NORTH);
|
||||
mainPanel.add(gradePanel, BorderLayout.NORTH);
|
||||
mainPanel.add(inputPanel, BorderLayout.CENTER);
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
mainPanel.add(messagePanel, BorderLayout.SOUTH);
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
startButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
startQuiz();
|
||||
}
|
||||
});
|
||||
|
||||
backButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showGradeSelectionPanel();
|
||||
}
|
||||
});
|
||||
|
||||
// Enter key handling
|
||||
countField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
startQuiz();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startQuiz() {
|
||||
String countText = countField.getText().trim();
|
||||
|
||||
if (countText.isEmpty()) {
|
||||
showMessage("Please enter question count", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int count = Integer.parseInt(countText);
|
||||
|
||||
if (count < 10 || count > 30) {
|
||||
showMessage("Question count must be between 10-30", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save question count to session
|
||||
QuizSession.getInstance().setQuestionCount(count);
|
||||
|
||||
// Jump to quiz interface
|
||||
mainFrame.showQuizPanel();
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
showMessage("Please enter a valid number", Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private void showMessage(String message, Color color) {
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
|
||||
public void updateGradeDisplay() {
|
||||
QuizSession session = QuizSession.getInstance();
|
||||
if (session.getAccountType() != null) {
|
||||
gradeLabel.setText("Current Grade: " + ((mathquiz.AccountType) session.getAccountType()).displayName());
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
countField.setText("");
|
||||
messageLabel.setText("");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import mathquiz.AccountType;
|
||||
|
||||
/**
|
||||
* Quiz Session Management Class
|
||||
* Singleton pattern, manages current user session information
|
||||
*/
|
||||
public class QuizSession {
|
||||
private static QuizSession instance;
|
||||
|
||||
private String currentUser;
|
||||
private AccountType accountType;
|
||||
private int questionCount;
|
||||
|
||||
private QuizSession() {
|
||||
// Private constructor
|
||||
}
|
||||
|
||||
public static QuizSession getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new QuizSession();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public String getCurrentUser() {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
public void setCurrentUser(String currentUser) {
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
public AccountType getAccountType() {
|
||||
return accountType;
|
||||
}
|
||||
|
||||
public void setAccountType(AccountType accountType) {
|
||||
this.accountType = accountType;
|
||||
}
|
||||
|
||||
public int getQuestionCount() {
|
||||
return questionCount;
|
||||
}
|
||||
|
||||
public void setQuestionCount(int questionCount) {
|
||||
this.questionCount = questionCount;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
currentUser = null;
|
||||
accountType = null;
|
||||
questionCount = 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,233 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import mathquiz.backend.EmailService;
|
||||
import mathquiz.backend.UserService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Registration Panel
|
||||
*/
|
||||
public class RegisterPanel extends JPanel {
|
||||
private final MainFrame mainFrame;
|
||||
private JTextField usernameField;
|
||||
private JTextField emailField;
|
||||
private JTextField verificationCodeField;
|
||||
private JButton sendCodeButton;
|
||||
private JButton registerButton;
|
||||
private JButton backButton;
|
||||
private JLabel messageLabel;
|
||||
private JLabel statusLabel;
|
||||
|
||||
private String currentEmail;
|
||||
private String sentVerificationCode;
|
||||
|
||||
public RegisterPanel(MainFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
usernameField = new JTextField(20);
|
||||
emailField = new JTextField(20);
|
||||
verificationCodeField = new JTextField(20);
|
||||
sendCodeButton = new JButton("Send Code");
|
||||
registerButton = new JButton("Complete Registration");
|
||||
backButton = new JButton("Back to Login");
|
||||
messageLabel = new JLabel("", JLabel.CENTER);
|
||||
statusLabel = new JLabel("Please enter username and email address to get verification code", JLabel.CENTER);
|
||||
|
||||
messageLabel.setForeground(Color.RED);
|
||||
statusLabel.setForeground(Color.BLUE);
|
||||
|
||||
// Set component styles
|
||||
sendCodeButton.setPreferredSize(new Dimension(120, 35));
|
||||
registerButton.setPreferredSize(new Dimension(150, 35));
|
||||
backButton.setPreferredSize(new Dimension(120, 35));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
|
||||
// Title
|
||||
JPanel titlePanel = new JPanel();
|
||||
JLabel titleLabel = new JLabel("User Registration", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
// Input panel
|
||||
JPanel inputPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(10, 10, 10, 10);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 0;
|
||||
inputPanel.add(new JLabel("Username:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(usernameField, gbc);
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(new JLabel(""), gbc); // Empty space for alignment
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 1;
|
||||
inputPanel.add(new JLabel("Email Address:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(emailField, gbc);
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(sendCodeButton, gbc);
|
||||
|
||||
gbc.gridx = 0; gbc.gridy = 2;
|
||||
inputPanel.add(new JLabel("Verification Code:"), gbc);
|
||||
gbc.gridx = 1;
|
||||
inputPanel.add(verificationCodeField, gbc);
|
||||
gbc.gridx = 2;
|
||||
inputPanel.add(registerButton, gbc);
|
||||
|
||||
// Button panel
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(backButton);
|
||||
|
||||
// Message panel
|
||||
JPanel messagePanel = new JPanel(new BorderLayout());
|
||||
messagePanel.add(statusLabel, BorderLayout.NORTH);
|
||||
messagePanel.add(messageLabel, BorderLayout.SOUTH);
|
||||
|
||||
// Assemble
|
||||
mainPanel.add(titlePanel, BorderLayout.NORTH);
|
||||
mainPanel.add(inputPanel, BorderLayout.CENTER);
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
mainPanel.add(messagePanel, BorderLayout.SOUTH);
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
sendCodeButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
sendVerificationCode();
|
||||
}
|
||||
});
|
||||
|
||||
registerButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
completeRegistration();
|
||||
}
|
||||
});
|
||||
|
||||
backButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showLoginPanel();
|
||||
}
|
||||
});
|
||||
|
||||
// Enter key handling
|
||||
verificationCodeField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
completeRegistration();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendVerificationCode() {
|
||||
String username = usernameField.getText().trim();
|
||||
String email = emailField.getText().trim();
|
||||
|
||||
if (username.isEmpty()) {
|
||||
showMessage("Please enter username", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (email.isEmpty()) {
|
||||
showMessage("Please enter email address", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidEmail(email)) {
|
||||
showMessage("Please enter a valid email address", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
EmailService emailService = new EmailService();
|
||||
String verificationCode = emailService.sendVerificationCode(email);
|
||||
|
||||
currentEmail = email;
|
||||
sentVerificationCode = verificationCode;
|
||||
|
||||
showMessage("Verification code has been sent to your email, please check", Color.GREEN);
|
||||
statusLabel.setText("Verification code sent, please enter code to complete registration");
|
||||
statusLabel.setForeground(Color.GREEN);
|
||||
|
||||
// Disable send button, enable register button
|
||||
sendCodeButton.setEnabled(false);
|
||||
registerButton.setEnabled(true);
|
||||
verificationCodeField.setEnabled(true);
|
||||
|
||||
} catch (Exception ex) {
|
||||
showMessage("Failed to send verification code: " + ex.getMessage(), Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private void completeRegistration() {
|
||||
String username = usernameField.getText().trim();
|
||||
String email = emailField.getText().trim();
|
||||
String code = verificationCodeField.getText().trim();
|
||||
|
||||
if (username.isEmpty() || email.isEmpty() || code.isEmpty()) {
|
||||
showMessage("Please enter username, email and verification code", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!email.equals(currentEmail)) {
|
||||
showMessage("Email address does not match", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!code.equals(sentVerificationCode)) {
|
||||
showMessage("Verification code is incorrect", Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
UserService userService = new UserService();
|
||||
userService.registerUser(email, username);
|
||||
|
||||
showMessage("Registration successful! Please set password", Color.GREEN);
|
||||
mainFrame.showPasswordSetupPanel(email);
|
||||
|
||||
} catch (Exception ex) {
|
||||
showMessage("Registration failed: " + ex.getMessage(), Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidEmail(String email) {
|
||||
return email.contains("@") && email.contains(".");
|
||||
}
|
||||
|
||||
private void showMessage(String message, Color color) {
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
emailField.setText("");
|
||||
verificationCodeField.setText("");
|
||||
messageLabel.setText("");
|
||||
statusLabel.setText("Please enter email address to get verification code");
|
||||
statusLabel.setForeground(Color.BLUE);
|
||||
sendCodeButton.setEnabled(true);
|
||||
registerButton.setEnabled(false);
|
||||
verificationCodeField.setEnabled(false);
|
||||
currentEmail = null;
|
||||
sentVerificationCode = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
package mathquiz.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Result Panel
|
||||
*/
|
||||
public class ResultPanel extends JPanel {
|
||||
private final MainFrame mainFrame;
|
||||
private JLabel scoreLabel;
|
||||
private JLabel messageLabel;
|
||||
private JButton continueButton;
|
||||
private JButton exitButton;
|
||||
|
||||
public ResultPanel(MainFrame mainFrame) {
|
||||
this.mainFrame = mainFrame;
|
||||
initializeComponents();
|
||||
setupLayout();
|
||||
setupEventHandlers();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
scoreLabel = new JLabel("", JLabel.CENTER);
|
||||
messageLabel = new JLabel("", JLabel.CENTER);
|
||||
continueButton = new JButton("Continue Quiz");
|
||||
exitButton = new JButton("Logout");
|
||||
|
||||
// Set styles
|
||||
scoreLabel.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
messageLabel.setFont(new Font("Arial", Font.PLAIN, 16));
|
||||
|
||||
continueButton.setPreferredSize(new Dimension(120, 40));
|
||||
exitButton.setPreferredSize(new Dimension(120, 40));
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
|
||||
// Title
|
||||
JPanel titlePanel = new JPanel();
|
||||
JLabel titleLabel = new JLabel("Quiz Results", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
titlePanel.add(titleLabel);
|
||||
|
||||
// Score display panel
|
||||
JPanel scorePanel = new JPanel(new BorderLayout());
|
||||
scorePanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
scorePanel.add(scoreLabel, BorderLayout.CENTER);
|
||||
scorePanel.add(messageLabel, BorderLayout.SOUTH);
|
||||
|
||||
// Button panel
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(continueButton);
|
||||
buttonPanel.add(exitButton);
|
||||
|
||||
// Assemble
|
||||
mainPanel.add(titlePanel, BorderLayout.NORTH);
|
||||
mainPanel.add(scorePanel, BorderLayout.CENTER);
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private void setupEventHandlers() {
|
||||
continueButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
continueQuiz();
|
||||
}
|
||||
});
|
||||
|
||||
exitButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exitQuiz();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setScore(int score, int totalQuestions) {
|
||||
// Calculate percentage
|
||||
int percentage = (int) Math.round((double) score / totalQuestions * 100);
|
||||
|
||||
// Display score with percentage (without % symbol)
|
||||
scoreLabel.setText("Your Score: " + score + "/" + totalQuestions + " (" + percentage + ")");
|
||||
|
||||
// Display different messages based on percentage
|
||||
String message;
|
||||
Color color;
|
||||
|
||||
if (percentage >= 90) {
|
||||
message = "Excellent! You answered " + score + " out of " + totalQuestions + " questions correctly";
|
||||
color = Color.GREEN;
|
||||
} else if (percentage >= 80) {
|
||||
message = "Good! You answered " + score + " out of " + totalQuestions + " questions correctly";
|
||||
color = Color.BLUE;
|
||||
} else if (percentage >= 70) {
|
||||
message = "Pass! You answered " + score + " out of " + totalQuestions + " questions correctly";
|
||||
color = Color.ORANGE;
|
||||
} else {
|
||||
message = "Need improvement! You answered " + score + " out of " + totalQuestions + " questions correctly";
|
||||
color = Color.RED;
|
||||
}
|
||||
|
||||
messageLabel.setText(message);
|
||||
messageLabel.setForeground(color);
|
||||
}
|
||||
|
||||
private void continueQuiz() {
|
||||
// Return to grade selection interface
|
||||
mainFrame.showGradeSelectionPanel();
|
||||
}
|
||||
|
||||
private void exitQuiz() {
|
||||
// Clear session information
|
||||
QuizSession.getInstance().clear();
|
||||
|
||||
// Return to login interface
|
||||
mainFrame.showLoginPanel();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue