added comments

This commit is contained in:
Trishaan committed 2025-12-01 10:48:52 -08:00
1 parent a22d20986e
commit b9b720665f
2 files changed
+93 -21

No files matched your search

@@ -1,5 +1,19 @@
package ca.bcit.comp2522.lab11; package ca.bcit.comp2522.lab11;
/**
* Represents a single quiz question containing a question prompt
* and one or more valid answers. A user-provided answer is considered
* correct if it matches any of the stored answers, ignoring case.
*
* This class performs validation to ensure question text and answer
* strings are never null or blank.
*
* @author Braeden Sowinski
* @author Nico Agostini
* @author Trishaan Shetty
* @author Calvin Arifianto
* @version 1.0.0
*/
public class Question public class Question
{ {
private static final int MIN_ANSWERS = 1; private static final int MIN_ANSWERS = 1;
@@ -7,6 +21,12 @@ public class Question
private final String question; private final String question;
private final String[] answers; private final String[] answers;
/**
* Validates that a string is not null or blank.
*
* @param str the string to validate
* @throws IllegalArgumentException if the string is null or blank
*/
private static void validateString(final String str) private static void validateString(final String str)
{ {
if (str == null || str.isBlank()) if (str == null || str.isBlank())
@@ -15,6 +35,15 @@ public class Question
} }
} }
/**
* Constructs a Question with a prompt and accepted answers.
*
* @param question the question text
* @param answers the list of valid answers
* @throws IllegalArgumentException if question is invalid,
* or if answers is empty,
* or if any individual answer is invalid
*/
public Question( public Question(
final String question, final String question,
final String[] answers final String[] answers
@@ -35,16 +64,33 @@ public class Question
this.answers = answers; this.answers = answers;
} }
/**
* Returns the question text.
*
* @return the question string
*/
public String getQuestion() public String getQuestion()
{ {
return this.question; return this.question;
} }
/**
* Returns the list of accepted answers.
*
* @return an array of valid answers
*/
public String[] getAnswers() public String[] getAnswers()
{ {
return this.answers; return this.answers;
} }
/**
* Checks whether a user's answer is correct.
* Matching is case-insensitive.
*
* @param userAnswer the answer provided by the user
* @return true if it matches one of the valid answers; false otherwise
*/
public boolean validateAnswer(final String userAnswer) public boolean validateAnswer(final String userAnswer)
{ {
for (final String answer : this.answers) for (final String answer : this.answers)
+47 -21
View File
@@ -22,6 +22,18 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
/**
* A timed quiz application that loads questions from an external file
* and presents them to the user in randomized order. The user has a
* limited amount of time to answer a fixed number of questions.
* Final results are shown when time expires or all questions are answered.
*
* @author Braeden Sowinski
* @author Nico Agostini
* @author Trishaan Shetty
* @author Calvin Arifianto
* @version 1.0.0
*/
public class Quiz extends Application public class Quiz extends Application
{ {
private static final int WIDTH = 800; private static final int WIDTH = 800;
@@ -48,7 +60,6 @@ public class Quiz extends Application
private Timeline timeline; private Timeline timeline;
// UI
private VBox root; private VBox root;
private Label questionLabel; private Label questionLabel;
private Label feedbackLabel; private Label feedbackLabel;
@@ -58,6 +69,11 @@ public class Quiz extends Application
private Button startButton; private Button startButton;
private Button playAgainButton; private Button playAgainButton;
/**
* Reads and loads quiz questions from a file.
*
* @param path the path to the quiz data file
*/
private void readQuestions(final Path path) private void readQuestions(final Path path)
{ {
if (!questions.isEmpty()) if (!questions.isEmpty())
@@ -74,7 +90,6 @@ public class Quiz extends Application
final String[] parts = line.split(DELIMITER); final String[] parts = line.split(DELIMITER);
if (parts.length < MIN_LENGTH) if (parts.length < MIN_LENGTH)
{ {
// Skip lines
continue; continue;
} }
@@ -97,10 +112,14 @@ public class Quiz extends Application
} }
} }
/**
* Initializes the UI and starts the JavaFX application.
*
* @param stage the primary stage
*/
@Override @Override
public void start(final Stage stage) public void start(final Stage stage)
{ {
root = new VBox(); root = new VBox();
root.setPrefSize(WIDTH, HEIGHT); root.setPrefSize(WIDTH, HEIGHT);
@@ -115,7 +134,6 @@ public class Quiz extends Application
startButton = new Button("Start quiz"); startButton = new Button("Start quiz");
playAgainButton = new Button("Play again"); playAgainButton = new Button("Play again");
// Initial UI state: game not started yet
answerField.setDisable(true); answerField.setDisable(true);
submitButton.setDisable(true); submitButton.setDisable(true);
playAgainButton.setDisable(true); playAgainButton.setDisable(true);
@@ -149,7 +167,6 @@ public class Quiz extends Application
} }
final Runnable submitAction = () -> { final Runnable submitAction = () -> {
// If game is not running
if (current == null) if (current == null)
{ {
return; return;
@@ -174,18 +191,13 @@ public class Quiz extends Application
wrongCount++; wrongCount++;
} }
// One chance per question: move immediately to next
currentQuestionIndex++; currentQuestionIndex++;
showNextQuestion(); showNextQuestion();
}; };
submitButton.setOnAction(event -> submitAction.run()); submitButton.setOnAction(event -> submitAction.run());
answerField.setOnAction(event -> submitAction.run()); answerField.setOnAction(event -> submitAction.run());
// Start quiz button
startButton.setOnAction(event -> startGame()); startButton.setOnAction(event -> startGame());
// Play again button (same as start, but different state)
playAgainButton.setOnAction(event -> startGame()); playAgainButton.setOnAction(event -> startGame());
stage.setScene(scene); stage.setScene(scene);
@@ -193,13 +205,17 @@ public class Quiz extends Application
stage.show(); stage.show();
} }
/**
* Starts a new quiz round, resets counters, shuffles questions,
* and initializes the timer.
*/
private void startGame() private void startGame()
{ {
correctCount = COUNTER_STARTER; correctCount = COUNTER_STARTER;
wrongCount = COUNTER_STARTER; wrongCount = COUNTER_STARTER;
remainingSeconds = START_TIME_SECS; remainingSeconds = START_TIME_SECS;
currentQuestionIndex = COUNTER_STARTER; currentQuestionIndex = COUNTER_STARTER;
feedbackLabel.setText(""); feedbackLabel.setText("");
questionLabel.setText(""); questionLabel.setText("");
@@ -211,7 +227,6 @@ public class Quiz extends Application
quizQuestions = new ArrayList<>(quizQuestions.subList(COUNTER_STARTER, NUM_QUESTIONS)); quizQuestions = new ArrayList<>(quizQuestions.subList(COUNTER_STARTER, NUM_QUESTIONS));
} }
// Timer
if (timeline != null) if (timeline != null)
{ {
timeline.stop(); timeline.stop();
@@ -237,13 +252,14 @@ public class Quiz extends Application
playAgainButton.setDisable(true); playAgainButton.setDisable(true);
playAgainButton.setVisible(false); playAgainButton.setVisible(false);
// Start with first question
showNextQuestion(); showNextQuestion();
} }
/**
* Displays the next question or ends the quiz if none remain.
*/
private void showNextQuestion() private void showNextQuestion()
{ {
if (currentQuestionIndex >= quizQuestions.size()) if (currentQuestionIndex >= quizQuestions.size())
{ {
endGame("You answered all questions."); endGame("You answered all questions.");
@@ -259,6 +275,9 @@ public class Quiz extends Application
updateStatusLabel(); updateStatusLabel();
} }
/**
* Updates the status label to show progress and remaining time.
*/
private void updateStatusLabel() private void updateStatusLabel()
{ {
if (quizQuestions.isEmpty()) if (quizQuestions.isEmpty())
@@ -267,16 +286,22 @@ public class Quiz extends Application
return; return;
} }
final int displayIndex = Math.min(currentQuestionIndex + ONE_SECOND, quizQuestions.size()); final int displayIndex =
Math.min(currentQuestionIndex + ONE_SECOND, quizQuestions.size());
statusLabel.setText( statusLabel.setText(
displayIndex + "/" + quizQuestions.size() displayIndex + "/" + quizQuestions.size()
+ " ::: " + remainingSeconds + "s remaining" + " ::: " + remainingSeconds + "s remaining"
); );
} }
/**
* Ends the game, stops the timer, and displays the final score.
*
* @param reason explanation for ending (e.g., time expired)
*/
private void endGame(final String reason) private void endGame(final String reason)
{ {
if (timeline != null) if (timeline != null)
{ {
timeline.stop(); timeline.stop();
@@ -284,9 +309,8 @@ public class Quiz extends Application
submitButton.setDisable(true); submitButton.setDisable(true);
answerField.setDisable(true); answerField.setDisable(true);
current = null; // mark game as ended current = null;
// Final score on screen
final String finalScore = final String finalScore =
reason + "\n\nFinal score:" reason + "\n\nFinal score:"
+ "\nCorrect: " + correctCount + "\nCorrect: " + correctCount
@@ -294,17 +318,19 @@ public class Quiz extends Application
feedbackLabel.setText(finalScore); feedbackLabel.setText(finalScore);
// Clear question + status, show restart UI
questionLabel.setText("Game over."); questionLabel.setText("Game over.");
statusLabel.setText(""); statusLabel.setText("");
// Show "Play again" button
playAgainButton.setVisible(true); playAgainButton.setVisible(true);
playAgainButton.setDisable(false); playAgainButton.setDisable(false);
startButton.setVisible(false); startButton.setVisible(false);
} }
/**
* Standard Java entry point. Launches the JavaFX app.
*
* @param args CLI arguments
*/
public static void main(final String[] args) public static void main(final String[] args)
{ {
launch(args); launch(args);