initial commit

This commit is contained in:
SowinskiBraeden committed 2025-11-14 17:23:25 -08:00
commit c4cc81a1ad
39 files changed
+1915

No files matched your search

@@ -0,0 +1,58 @@
package ca.bcit.comp2522.project;
import java.util.Random;
/**
* Country class
*
* @author Braeden Sowinski
* @version 1.0.0
*/
public class Country
{
private static final int NUMBER_OF_FACTS = 3;
private final String name;
private final String capitalCityName;
private final String[] facts;
private static void validateString(final String str)
{
if (str == null || str.isBlank())
{
throw new IllegalArgumentException("Invalid string");
}
}
public Country(
final String name,
final String capitalCityName,
final String[] facts
) {
validateString(name);
validateString(capitalCityName);
this.name = name;
this.capitalCityName = capitalCityName;
this.facts = facts;
}
public String getName()
{
return this.name;
}
public String getCapital()
{
return this.capitalCityName;
}
public String getRandomFact()
{
final Random rand;
rand = new Random();
return this.facts[rand.nextInt(this.facts.length)];
}
}
@@ -0,0 +1,56 @@
package ca.bcit.comp2522.project;
import java.util.Scanner;
/**
* Main program entry to access a games menu
*
* @author Braeden Sowinski
* @version 1.0.0
*/
public class Main
{
public static void main(final String[] args)
{
final Scanner scanner;
scanner = new Scanner(System.in);
boolean run = true;
do {
final String input;
System.out.println("Select a game: ");
System.out.println("Word Game (W)");
System.out.println("Number Game (N)");
System.out.println("My Game (M)");
System.out.println("Quit (Q)");
System.out.print("> ");
input = scanner.nextLine().toUpperCase();
switch (input) {
case "W":
System.out.println("Word game...");
break;
case "N":
System.out.println("Number game...");
break;
case "M":
System.out.println("My game...");
break;
case "Q":
System.out.println("Quitting...");
run = false;
break;
default:
System.out.println("Invalid input: " + input);
break;
}
} while (run);
scanner.close();
}
}
@@ -0,0 +1,19 @@
package ca.bcit.comp2522.project;
import javafx.application.Application;
import javafx.stage.Stage;
public class Mines extends Application
{
@Override
public void start(final Stage s)
{
s.setTitle("MineSweeper Random");
s.show();
}
public static void main(final String[] args)
{
launch(args);
}
}
@@ -0,0 +1,50 @@
package ca.bcit.comp2522.project;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
public class NumberGame extends Application
{
@Override
public void start(final Stage stage)
{
final VBox layout;
final Scene scene;
layout = createLayout(); // see below
scene = new Scene(layout, 300, 200);
stage.setScene(scene);
stage.setTitle("20 Number Challenge");
stage.show();
}
private VBox createLayout()
{
final Label greeting;
final TextField textField;
final Button button;
greeting = new Label("Enter your name:");
textField = new TextField();
button = new Button("Click me!");
button.setOnAction(e -> greeting.setText("Hello, " + textField.getText()
+ "!"));
// or
//button.setOnAction(event -> assignAction(greeting, textField, button));
return new VBox(greeting, textField, button);
}
void assignAction(final Label l, final TextField t, final Button b)
{
l.setText("Hello, " + t.getText() + "!");
}
public static void main(final String[] args)
{
launch(args);
}
}
@@ -0,0 +1,196 @@
package ca.bcit.comp2522.project;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* Score manager for the word game.
*
* @author Braeden Sowinski
* @version 1.0.0
*/
public class Score
{
private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final int FIRST_GUESS_POINTS = 2;
private static final int SECOND_GUESS_POINTS = 1;
private static final int SPLIT_VALUE = 1;
private final String dateTimePlayed;
private final int numGamesPlayed;
private final int numCorrectFirstAttempt;
private final int numCorrectSecondAttempt;
private final int numIncorrectTwoAttempts;
private final int score;
public static void appendScoreToFile(
final Score score,
final String scoreFilePath
) {
try
{
final BufferedWriter writer;
writer = new BufferedWriter(new FileWriter(scoreFilePath, true));
writer.write(score.toString());
writer.newLine();
writer.newLine();
writer.close();
}
catch (final IOException e)
{
System.err.println("Failed to write score.txt");
}
}
public static List<Score> readScoresFromFile(final String scoreFilePath)
{
final List<Score> scores;
scores = new ArrayList<>();
try
{
final BufferedReader reader;
reader = new BufferedReader(new FileReader(scoreFilePath));
String line;
while ((line = reader.readLine()) != null)
{
if (!line.isBlank() && line.contains("Date and Time: "))
{
final DateTimeFormatter formatter;
final String dateTime;
final Score score;
final String games;
final String correctFirst;
final String correctSecond;
final String incorrect;
formatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
dateTime = line.split(": ")[SPLIT_VALUE];
System.out.println("debug " + dateTime);
games = reader.readLine().split(": ")[SPLIT_VALUE];
correctFirst = reader.readLine().split(": ")[SPLIT_VALUE];
correctSecond = reader.readLine().split(": ")[SPLIT_VALUE];
incorrect = reader.readLine().split(": ")[SPLIT_VALUE];
reader.readLine(); // Skip over score line
score = new Score(
LocalDateTime.parse(dateTime, formatter),
Integer.parseInt(games),
Integer.parseInt(correctFirst),
Integer.parseInt(correctSecond),
Integer.parseInt(incorrect)
);
scores.add(score);
}
}
reader.close();
} catch (final IOException e)
{
System.err.println("Failed to open score log file.");
}
return scores;
}
public static Score getHighScore(final List<Score> scores)
{
return scores.stream()
.min(Comparator.comparingInt(Score::getScore))
.orElse(null);
}
public static boolean isHighScore(
final Score score,
final List<Score> scores
) {
final Score highScore;
highScore = Score.getHighScore(scores);
return (highScore == null ||
highScore.getScore() < score.getScore());
}
public Score(
final LocalDateTime dateTime,
final int numGamesPlayed,
final int numCorrectFirstAttempt,
final int numCorrectSecondAttempt,
final int numIncorrectTwoAttempts
) {
final DateTimeFormatter formatter;
formatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
this.dateTimePlayed = dateTime.format(formatter);
this.numGamesPlayed = numGamesPlayed;
this.numCorrectFirstAttempt = numCorrectFirstAttempt;
this.numCorrectSecondAttempt = numCorrectSecondAttempt;
this.numIncorrectTwoAttempts = numIncorrectTwoAttempts;
this.score = this.numCorrectFirstAttempt * FIRST_GUESS_POINTS +
this.numCorrectSecondAttempt * SECOND_GUESS_POINTS;
}
public String getDateTimePlayed()
{
return this.dateTimePlayed;
}
@Override
public String toString()
{
final StringBuilder log;
log = new StringBuilder();
log.append("Date and Time: ");
log.append(this.dateTimePlayed);
log.append("\n");
log.append("Games Played: ");
log.append(this.numGamesPlayed);
log.append("\n");
log.append("Correct First Attempts: ");
log.append(this.numCorrectFirstAttempt);
log.append("\n");
log.append("Correct Second Attempts: ");
log.append(this.numCorrectSecondAttempt);
log.append("\n");
log.append("Incorrect Attempts: ");
log.append(this.numIncorrectTwoAttempts);
log.append("\n");
log.append("Total Score: ");
log.append(this.score);
return log.toString();
}
public int getScore()
{
return this.score;
}
public float calculateAverage()
{
return (float) this.score / (float) this.numGamesPlayed;
}
}
@@ -0,0 +1,300 @@
package ca.bcit.comp2522.project;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.stream.Stream;
/**
* @author Braeden Sowinski
* @version 1.0.0
*/
public class World
{
private static final String SCORE_PATH = "./data/score.txt";
private static final int COUNTRY_PARAM = 0;
private static final int CAPITAL_PARAM = 1;
private static final int NUMBER_OF_FACTS = 3;
private static final String BASE_PATH = "./data/facts";
private static final int NUMBER_OF_QUESTIONS = 10;
private static final int QUESTION_NUM_OFFSET = 1;
private static final int QUEST_ASK_CAPITAL = 0;
private static final int QUEST_ASK_COUNTRY = 1;
private static final int QUEST_ASK_FACT = 2;
private static final int QUESTION_TYPES = 3;
private static final int MAX_ATTEMPTS = 2;
private static final int FIRST_ATTEMPT = 0;
private static final int SPLIT_DATE = 0;
private static final int SPLIT_TIME = 1;
private static final int FIRST_ATTEMPT_SCORE = 0;
private static final int SECOND_ATTEMPT_SCORE = 1;
private static final int INCORRECT_SCORE = 2;
private static final int DEFAULT_SCORE = 0;
private final Map<String, Country> countries;
private static Country readCountryData(
final String line,
final BufferedReader reader
)
throws IOException
{
final String countryName;
final String countryCapital;
final String[] facts;
countryName = line.split(":")[COUNTRY_PARAM];
countryCapital = line.split(":")[CAPITAL_PARAM];
facts = new String[NUMBER_OF_FACTS];
for (int i = 0; i < NUMBER_OF_FACTS; i++)
{
facts[i] = reader.readLine();
}
return new Country(countryName, countryCapital, facts);
}
public World()
throws IOException
{
this.countries = new HashMap<>();
try (Stream<Path> walk = Files.walk(Paths.get(BASE_PATH)))
{
List<Path> filesInFolder = walk
.filter(Files::isRegularFile)
.toList();
for (final Path file : filesInFolder)
{
final BufferedReader reader;
reader = new BufferedReader(new FileReader(file.toString()));
String line;
while ((line = reader.readLine()) != null)
{
if (line.isBlank())
{
continue;
}
final Country country;
country = readCountryData(line, reader);
this.countries.put(country.getName(), country);
}
}
}
catch (final IOException e)
{
System.err.println("Error accessing the folder: " + e.getMessage());
}
}
private void checkAnswer(
final String correctAnswer,
final Scanner scanner,
final int[] scores
) {
for (int i = 0; i < MAX_ATTEMPTS; i++)
{
final String answer;
System.out.print("> ");
answer = scanner.nextLine();
if (answer.equalsIgnoreCase(correctAnswer))
{
if (i == FIRST_ATTEMPT)
{
scores[FIRST_ATTEMPT_SCORE]++;
}
else
{
scores[SECOND_ATTEMPT_SCORE]++;
}
System.out.println("CORRECT!");
return;
}
System.out.println("INCORRECT!");
}
scores[INCORRECT_SCORE]++;
System.out.printf("The correct answer was %s\n", correctAnswer);
}
private void startTrivia(
final Scanner scanner,
final int[] scores
) {
for (int i = 0; i < NUMBER_OF_QUESTIONS; i++)
{
System.out.printf("Question %d:\n", i + QUESTION_NUM_OFFSET);
final Random rand;
final Country country;
final String key;
final List<String> keys;
final int questionType;
rand = new Random();
keys = new ArrayList<>(this.countries.keySet());
key = keys.get(rand.nextInt(keys.size()));
questionType = rand.nextInt(QUESTION_TYPES);
country = this.countries.get(key);
switch (questionType)
{
case QUEST_ASK_CAPITAL:
System.out.println("What is the country of the following capital?");
System.out.println(country.getCapital());
checkAnswer(country.getName(), scanner, scores);
break;
case QUEST_ASK_COUNTRY:
System.out.println("What is the capital of the following country?");
System.out.println(country.getName());
checkAnswer(country.getCapital(), scanner, scores);
break;
case QUEST_ASK_FACT:
System.out.println("What is the country of the following fact?");
System.out.println(country.getRandomFact());
checkAnswer(country.getName(), scanner, scores);
break;
}
}
}
public void runTrivia()
{
final Scanner scanner;
Score score;
boolean continuePlaying;
continuePlaying = true;
scanner = new Scanner(System.in);
final int[] scores;
int gamesPlayed;
scores = new int[]{DEFAULT_SCORE,DEFAULT_SCORE,DEFAULT_SCORE};
gamesPlayed = DEFAULT_SCORE;
do
{
gamesPlayed++;
this.startTrivia(scanner, scores);
score = new Score(
LocalDateTime.now(),
gamesPlayed,
scores[FIRST_ATTEMPT_SCORE],
scores[SECOND_ATTEMPT_SCORE],
scores[INCORRECT_SCORE]
);
System.out.println(score);
do
{
System.out.println("\nDo you want to play again?");
System.out.print("> ");
final String playAgain;
playAgain = scanner.nextLine();
if (playAgain.equalsIgnoreCase("no"))
{
continuePlaying = false;
break;
}
else if (playAgain.equalsIgnoreCase("yes"))
{
// break inner do-while loop
break;
}
else
{
System.out.printf("Invalid option \"%s\"\n", playAgain);
}
} while (true);
} while (continuePlaying);
scanner.close();
final List<Score> history;
history = Score.readScoresFromFile(SCORE_PATH);
Score.appendScoreToFile(score, SCORE_PATH);
if (Score.isHighScore(score, history))
{
System.out.printf(
"CONGRATULATIONS! You have a new high score with an average of %.2f points per game; ",
score.calculateAverage()
);
final Score prevHighScore;
prevHighScore = Score.getHighScore(history);
if (prevHighScore == null)
{
return;
}
System.out.printf(
"the previous record was %.2f points per game ",
prevHighScore.calculateAverage()
);
System.out.printf(
"on %s at %s.\n",
prevHighScore.getDateTimePlayed().split(" ")[SPLIT_DATE],
prevHighScore.getDateTimePlayed().split(" ")[SPLIT_TIME]
);
}
}
public static void main(final String[] args)
{
final World test;
try
{
test = new World();
}
catch (final IOException e)
{
throw new RuntimeException(e);
}
test.runTrivia();
}
}
@@ -0,0 +1,143 @@
package ca.bcit.comp2522.project;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ScoreTest {
private static final String SCORE_FILE = "test_score.txt";
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@BeforeEach
void setUp() throws IOException {
// Clear the score file before each test to ensure no leftover data
new FileWriter(SCORE_FILE, false).close();
}
@Test
void testScoreCalculation() {
// Testing score calculation based on correct first and second attempts
Score score = new Score(LocalDateTime.now(), 1, 6, 2, 1); // 6 first attempts (2 points each), 2 second attempts (1 point each)
assertEquals(14, score.getScore(), "Score should be 14 points (6 * 2 + 2 * 1)");
}
@Test
void testToStringFormat() {
// Testing the formatting of the toString() method
LocalDateTime dateTime = LocalDateTime.now();
Score score = new Score(dateTime, 1, 6, 2, 1);
String expected = String.format(
"Date and Time: %s\nGames Played: 1\nCorrect First Attempts: 6\nCorrect Second Attempts: 2\nIncorrect Attempts: 1\nScore: 14 points\n",
dateTime.format(formatter)
);
assertEquals(expected, score.toString(), "The toString format should match the expected format.");
}
@Test
void testAppendAndRetrieveLargeNumberOfScores() throws IOException {
// Create 25 scores and write them to the file
for (int i = 0; i < 25; i++) {
Score score = new Score(LocalDateTime.now(), 1, i + 1, (i % 3) + 1, (i % 2) + 1);
Score.appendScoreToFile(score, SCORE_FILE);
}
// Read scores from the file
List<Score> scores = Score.readScoresFromFile(SCORE_FILE);
// Validate the number of scores and their content
assertEquals(25, scores.size(), "Twenty-five scores should have been read from the file.");
for (int i = 0; i < 25; i++) {
int expectedScore = ((i + 1) * 2) + ((i % 3) + 1);
assertEquals(expectedScore, scores.get(i).getScore(), "Score for entry " + i + " should match the calculated value.");
}
}
@Test
void testCheckForNewHighScore() throws IOException {
// Create some initial scores and add them to the file
Score score1 = new Score(LocalDateTime.now(), 1, 6, 2, 1); // 14 points
Score score2 = new Score(LocalDateTime.now(), 1, 9, 1, 0); // 19 points
Score.appendScoreToFile(score1, SCORE_FILE);
Score.appendScoreToFile(score2, SCORE_FILE);
// Add a new score that is NOT a high score
Score score3 = new Score(LocalDateTime.now(), 1, 7, 2, 1); // 16 points
Score.appendScoreToFile(score3, SCORE_FILE);
// Read scores from the file
List<Score> scores = Score.readScoresFromFile(SCORE_FILE);
// Verify the highest score is still 19
int highScore = scores.stream().mapToInt(Score::getScore).max().orElse(0);
assertEquals(19, highScore, "The highest score should still be 19 points.");
}
@Test
void testNewHighScore() throws IOException {
// Create some initial scores and add them to the file
Score score1 = new Score(LocalDateTime.now(), 1, 6, 2, 1); // 14 points
Score score2 = new Score(LocalDateTime.now(), 1, 9, 1, 0); // 19 points
Score.appendScoreToFile(score1, SCORE_FILE);
Score.appendScoreToFile(score2, SCORE_FILE);
// Add a new score that IS a high score
Score score3 = new Score(LocalDateTime.now(), 1, 10, 1, 0); // 21 points
Score.appendScoreToFile(score3, SCORE_FILE);
// Read scores from the file
List<Score> scores = Score.readScoresFromFile(SCORE_FILE);
// Verify the highest score is now 21
int highScore = scores.stream().mapToInt(Score::getScore).max().orElse(0);
assertEquals(21, highScore, "The highest score should now be 21 points.");
}
@Test
void testAppendAndCheckMultipleReads() throws IOException {
// Create initial scores and add them to the file
for (int i = 0; i < 5; i++) {
Score score = new Score(LocalDateTime.now(), 1, 5 + i, 1, 1); // Variable scores
Score.appendScoreToFile(score, SCORE_FILE);
}
// Perform the first read
List<Score> scores1 = Score.readScoresFromFile(SCORE_FILE);
assertEquals(5, scores1.size(), "There should be 5 scores after the first write and read.");
// Add more scores to the file
for (int i = 5; i < 10; i++) {
Score score = new Score(LocalDateTime.now(), 1, 5 + i, 1, 1); // Variable scores
Score.appendScoreToFile(score, SCORE_FILE);
}
// Perform the second read
List<Score> scores2 = Score.readScoresFromFile(SCORE_FILE);
assertEquals(10, scores2.size(), "There should be 10 scores after the second write and read.");
}
@Test
void testEmptyScoreFile() throws IOException {
// Test reading from an empty score file, should return an empty list
List<Score> scores = Score.readScoresFromFile(SCORE_FILE);
assertTrue(scores.isEmpty(), "Reading from an empty file should return an empty list.");
}
@AfterEach
void tearDown() {
// Clean up by deleting the test score file after each test
new File(SCORE_FILE).delete();
}
}