diff --git a/Dao/pom.xml b/Dao/pom.xml
index aca1c23..701da80 100644
--- a/Dao/pom.xml
+++ b/Dao/pom.xml
@@ -40,12 +40,10 @@
org.slf4jslf4j-api
- 1.7.16ch.qos.logbacklogback-classic
- 1.2.6
diff --git a/Dao/src/test/java/sudoku/dao/FileSudokuBoardDaoTest.java b/Dao/src/test/java/sudoku/dao/FileSudokuBoardDaoTest.java
index ceca3fb..19c6596 100644
--- a/Dao/src/test/java/sudoku/dao/FileSudokuBoardDaoTest.java
+++ b/Dao/src/test/java/sudoku/dao/FileSudokuBoardDaoTest.java
@@ -9,7 +9,7 @@
import org.junit.jupiter.api.Assertions;
import sudoku.dao.factories.SudokuBoardDaoFactory;
import sudoku.dao.interfaces.Dao;
-import sudoku.model.exceptions.InvalidSudokuException;
+import sudoku.model.exceptions.FillingBoardSudokuException;
import sudoku.model.models.SudokuBoard;
import sudoku.model.solver.BacktrackingSudokuSolver;
@@ -38,7 +38,7 @@ public void testWriteAndRead() {
SudokuBoard sampleBoard = new SudokuBoard(new BacktrackingSudokuSolver());
try {
sampleBoard.solveGame();
- } catch (InvalidSudokuException e) {
+ } catch (FillingBoardSudokuException e) {
e.printStackTrace();
}
diff --git a/JdbcDao/pom.xml b/JdbcDao/pom.xml
index 590217a..57d6d4a 100644
--- a/JdbcDao/pom.xml
+++ b/JdbcDao/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
diff --git a/JdbcDao/src/main/java/sudoku/jdbcdao/JdbcSudokuBoardDao.java b/JdbcDao/src/main/java/sudoku/jdbcdao/JdbcSudokuBoardDao.java
index c3f3329..baf69d8 100644
--- a/JdbcDao/src/main/java/sudoku/jdbcdao/JdbcSudokuBoardDao.java
+++ b/JdbcDao/src/main/java/sudoku/jdbcdao/JdbcSudokuBoardDao.java
@@ -1,7 +1,7 @@
package sudoku.jdbcdao;
-import static sudokujdbc.jooq.generated.Tables.SUDOKU_BOARD;
-import static sudokujdbc.jooq.generated.Tables.SUDOKU_FIELD;
+import static sudokujdbc.jooq.generated.Tables.SUDOKU_BOARDS;
+import static sudokujdbc.jooq.generated.Tables.SUDOKU_FIELDS;
import java.sql.Connection;
import java.sql.DriverManager;
@@ -26,6 +26,9 @@ public class JdbcSudokuBoardDao implements Dao {
private DSLContext dsl;
public JdbcSudokuBoardDao(String url) {
+ if (url == null || url.trim().isEmpty()) {
+ throw new IllegalArgumentException("URL cannot be null or empty");
+ }
this.url = url;
}
@@ -48,18 +51,18 @@ public void write(String name, SudokuBoard board) throws JdbcDaoWriteException,
connect();
connection.setAutoCommit(false);
- var boardId = dsl.insertInto(SUDOKU_BOARD)
- .columns(SUDOKU_BOARD.NAME)
+ var boardId = dsl.insertInto(SUDOKU_BOARDS)
+ .columns(SUDOKU_BOARDS.NAME)
.values(name)
- .returning(SUDOKU_BOARD.ID)
+ .returning(SUDOKU_BOARDS.ID)
.fetchOne()
.getId();
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
int value = board.getField(row, col).getValue();
- dsl.insertInto(SUDOKU_FIELD)
- .columns(SUDOKU_FIELD.BOARD_ID, SUDOKU_FIELD.ROW, SUDOKU_FIELD.COLUMN, SUDOKU_FIELD.VALUE)
+ dsl.insertInto(SUDOKU_FIELDS)
+ .columns(SUDOKU_FIELDS.BOARD_ID, SUDOKU_FIELDS.ROW, SUDOKU_FIELDS.COLUMN, SUDOKU_FIELDS.VALUE)
.values(boardId, row, col, value)
.execute();
}
@@ -83,8 +86,8 @@ public SudokuBoard read(String name) throws JdbcDaoReadException {
try {
connect();
- var boardRecord = dsl.selectFrom(SUDOKU_BOARD)
- .where(SUDOKU_BOARD.NAME.eq(name))
+ var boardRecord = dsl.selectFrom(SUDOKU_BOARDS)
+ .where(SUDOKU_BOARDS.NAME.eq(name))
.fetchOne();
if (boardRecord == null) {
@@ -93,8 +96,8 @@ public SudokuBoard read(String name) throws JdbcDaoReadException {
SudokuBoard board = new SudokuBoard(new BacktrackingSudokuSolver());
- dsl.selectFrom(SUDOKU_FIELD)
- .where(SUDOKU_FIELD.BOARD_ID.eq(boardRecord.getId()))
+ dsl.selectFrom(SUDOKU_FIELDS)
+ .where(SUDOKU_FIELDS.BOARD_ID.eq(boardRecord.getId()))
.forEach(record -> {
int row = record.getRow();
int col = record.getColumn();
@@ -114,9 +117,9 @@ public SudokuBoard read(String name) throws JdbcDaoReadException {
public List names() throws JdbcDaoReadException {
try {
connect();
- return dsl.select(SUDOKU_BOARD.NAME)
- .from(SUDOKU_BOARD)
- .fetch(SUDOKU_BOARD.NAME);
+ return dsl.select(SUDOKU_BOARDS.NAME)
+ .from(SUDOKU_BOARDS)
+ .fetch(SUDOKU_BOARDS.NAME);
} catch (Exception e) {
throw new JdbcDaoReadException(e);
} finally {
diff --git a/JdbcDao/src/main/java/sudoku/jdbcdao/database/database-schema.md b/JdbcDao/src/main/java/sudoku/jdbcdao/database/database-schema.md
new file mode 100644
index 0000000..a910e31
--- /dev/null
+++ b/JdbcDao/src/main/java/sudoku/jdbcdao/database/database-schema.md
@@ -0,0 +1,16 @@
+```mermaid
+erDiagram
+ SUDOKU_BOARDS {
+ int id PK
+ string name
+ }
+ SUDOKU_FIELDS {
+ int id PK
+ int board_id FK
+ int row
+ int column
+ int value
+ }
+
+ SUDOKU_FIELDS }|--|| SUDOKU_BOARDS : board_id
+```
\ No newline at end of file
diff --git a/JdbcDao/src/main/java/sudoku/jdbcdao/database/schema.sql b/JdbcDao/src/main/java/sudoku/jdbcdao/database/schema.sql
index 2181d66..bd82161 100644
--- a/JdbcDao/src/main/java/sudoku/jdbcdao/database/schema.sql
+++ b/JdbcDao/src/main/java/sudoku/jdbcdao/database/schema.sql
@@ -1,13 +1,13 @@
-CREATE TABLE IF NOT EXISTS SUDOKU_BOARD (
+CREATE TABLE IF NOT EXISTS SUDOKU_BOARDS (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE
);
-CREATE TABLE IF NOT EXISTS SUDOKU_FIELD (
+CREATE TABLE IF NOT EXISTS SUDOKU_FIELDS (
id INTEGER PRIMARY KEY AUTOINCREMENT,
board_id INTEGER,
row INTEGER,
column INTEGER,
value INTEGER,
- FOREIGN KEY (board_id) REFERENCES SUDOKU_BOARD (id)
+ FOREIGN KEY (board_id) REFERENCES SUDOKU_BOARDS (id)
);
diff --git a/JdbcDao/src/main/java/sudoku/jdbcdao/exceptions/LocalizedException.java b/JdbcDao/src/main/java/sudoku/jdbcdao/exceptions/LocalizedException.java
index 74e78b1..0c1279e 100644
--- a/JdbcDao/src/main/java/sudoku/jdbcdao/exceptions/LocalizedException.java
+++ b/JdbcDao/src/main/java/sudoku/jdbcdao/exceptions/LocalizedException.java
@@ -1,17 +1,42 @@
package sudoku.jdbcdao.exceptions;
+import java.util.Locale;
import java.util.ResourceBundle;
+/**
+ * Represents a localized exception base class that can be thrown by the JdbcDao
+ * module.
+ * This exception is used to provide localized error messages to the user.
+ */
public class LocalizedException extends Exception {
+ /**
+ * Retrieves the localized message for the given message key.
+ *
+ * @param messageKey the key of the message to retrieve
+ * @return the localized message associated with the key
+ */
private static String getLocalizedMessage(String messageKey) {
- ResourceBundle bundle = ResourceBundle.getBundle("JdbcDaoExceptions"); // remember that resource bundles must be
+ ResourceBundle bundle = ResourceBundle.getBundle("JdbcDaoExceptions", Locale.getDefault());
return bundle.getString(messageKey);
}
+ /**
+ * Constructs a new LocalizedException with the specified messenger.
+ *
+ * @param messenger the JdbcDaoMessageKey representing the localized message
+ * key.
+ */
public LocalizedException(JdbcDaoMessageKey messenger) {
super(getLocalizedMessage(messenger.getKey()));
}
+ /**
+ * Constructs a new LocalizedException with the specified messenger and cause.
+ *
+ * @param messenger the JdbcDaoMessageKey representing the localized message
+ * key.
+ * @param cause the Throwable that caused this exception to be thrown.
+ */
public LocalizedException(JdbcDaoMessageKey messenger, Throwable cause) {
super(getLocalizedMessage(messenger.getKey()), cause);
}
diff --git a/JdbcDao/src/test/java/sudoku/jdbcdao/JdbcSudokuBoardDaoTest.java b/JdbcDao/src/test/java/sudoku/jdbcdao/JdbcSudokuBoardDaoTest.java
index d59bca2..0e57360 100644
--- a/JdbcDao/src/test/java/sudoku/jdbcdao/JdbcSudokuBoardDaoTest.java
+++ b/JdbcDao/src/test/java/sudoku/jdbcdao/JdbcSudokuBoardDaoTest.java
@@ -15,42 +15,40 @@
import java.sql.SQLException;
import static org.junit.jupiter.api.Assertions.*;
-import static sudokujdbc.jooq.generated.Tables.SUDOKU_BOARD;
-import static sudokujdbc.jooq.generated.Tables.SUDOKU_FIELD;
+import static sudokujdbc.jooq.generated.Tables.SUDOKU_BOARDS;
+import static sudokujdbc.jooq.generated.Tables.SUDOKU_FIELDS;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class JdbcSudokuBoardDaoTest {
private static final String TEST_DB_URL = "jdbc:sqlite:target/test_sudoku.db";
private Connection connection;
- private DSLContext dsl;
-
-
- @BeforeAll
- public void setUp() throws SQLException {
- connection = DriverManager.getConnection(TEST_DB_URL);
- dsl = DSL.using(connection, SQLDialect.SQLITE);
-
- dsl.createTableIfNotExists(SUDOKU_BOARD)
- .columns(SUDOKU_BOARD.fields())
- .execute();
-
- dsl.createTableIfNotExists(SUDOKU_FIELD)
- .columns(SUDOKU_FIELD.fields())
- .execute();
- }
+ private DSLContext dsl;
+
+ @BeforeAll
+ public void setUp() throws SQLException {
+ connection = DriverManager.getConnection(TEST_DB_URL);
+ dsl = DSL.using(connection, SQLDialect.SQLITE);
+ dsl.createTableIfNotExists(SUDOKU_BOARDS)
+ .columns(SUDOKU_BOARDS.fields())
+ .execute();
+
+ dsl.createTableIfNotExists(SUDOKU_FIELDS)
+ .columns(SUDOKU_FIELDS.fields())
+ .execute();
+ }
@AfterEach
public void tearDown() throws SQLException {
- dsl.deleteFrom(SUDOKU_FIELD).execute();
- dsl.deleteFrom(SUDOKU_BOARD).execute();
+ dsl.deleteFrom(SUDOKU_FIELDS).execute();
+ dsl.deleteFrom(SUDOKU_BOARDS).execute();
}
@AfterAll
public void cleanUp() throws SQLException {
- dsl.dropTableIfExists(SUDOKU_FIELD).execute();
- dsl.dropTableIfExists(SUDOKU_BOARD).execute();
+ dsl.dropTableIfExists(SUDOKU_FIELDS).execute();
+ dsl.dropTableIfExists(SUDOKU_BOARDS).execute();
connection.close();
}
@@ -98,7 +96,8 @@ public void testReadNonExistentBoard() {
@Test
public void testWriteException() {
try (Dao dao = new JdbcSudokuBoardDao(TEST_DB_URL)) {
- assertThrows(JdbcDaoWriteException.class, () -> dao.write("", new SudokuBoard(new BacktrackingSudokuSolver())));
+ assertThrows(JdbcDaoWriteException.class,
+ () -> dao.write("", new SudokuBoard(new BacktrackingSudokuSolver())));
} catch (Exception e) {
fail(e);
}
diff --git a/JdbcDao/src/test/java/sudoku/jdbcdao/resources/test_sudoku.db b/JdbcDao/src/test/java/sudoku/jdbcdao/resources/test_sudoku.db
index 9fc0515..0af2447 100644
Binary files a/JdbcDao/src/test/java/sudoku/jdbcdao/resources/test_sudoku.db and b/JdbcDao/src/test/java/sudoku/jdbcdao/resources/test_sudoku.db differ
diff --git a/JdbcDao/sudoku.db b/JdbcDao/sudoku.db
index 3774d5d..0af2447 100644
Binary files a/JdbcDao/sudoku.db and b/JdbcDao/sudoku.db differ
diff --git a/Model/src/main/java/sudoku/model/exceptions/FillingBoardSudokuException.java b/Model/src/main/java/sudoku/model/exceptions/FillingBoardSudokuException.java
new file mode 100644
index 0000000..e656d83
--- /dev/null
+++ b/Model/src/main/java/sudoku/model/exceptions/FillingBoardSudokuException.java
@@ -0,0 +1,54 @@
+package sudoku.model.exceptions;
+
+/**
+ * Exception thrown when there is an error during the process of filling a
+ * Sudoku board.
+ * This exception typically indicates issues encountered while populating the
+ * board with values.
+ *
+ *
+ * This exception extends {@link LocalizedModelException}, which provides
+ * support
+ * for localized error messages based on {@link ModelMessageKey}.
+ *
+ *
+ *
+ * The default error message is retrieved using the
+ * {@link ModelMessageKey#FILLING_BOARD_ERROR}
+ * key from the resource bundle.
+ *
+ *
+ *
+ * This exception can optionally wrap another throwable as its cause, providing
+ * additional context or information about the error.
+ *
+ *
+ * @see LocalizedModelException
+ * @see ModelMessageKey
+ */
+public class FillingBoardSudokuException extends LocalizedModelException {
+ /**
+ * Constructs a new FillingBoardSudokuException with a default error message
+ * key.
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#FILLING_BOARD_ERROR}.
+ */
+ public FillingBoardSudokuException() {
+ super(ModelMessageKey.FILLING_BOARD_ERROR);
+ }
+
+ /**
+ * Constructs a new FillingBoardSudokuException with the specified cause and
+ * a default error message key.
+ *
+ *
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#FILLING_BOARD_ERROR}.
+ *
+ *
+ * @param cause the cause of the exception
+ */
+ public FillingBoardSudokuException(Throwable cause) {
+ super(ModelMessageKey.FILLING_BOARD_ERROR, cause);
+ }
+}
diff --git a/Model/src/main/java/sudoku/model/exceptions/InvalidSudokuException.java b/Model/src/main/java/sudoku/model/exceptions/InvalidSudokuException.java
index ef469eb..0d58336 100644
--- a/Model/src/main/java/sudoku/model/exceptions/InvalidSudokuException.java
+++ b/Model/src/main/java/sudoku/model/exceptions/InvalidSudokuException.java
@@ -1,7 +1,53 @@
package sudoku.model.exceptions;
-public class InvalidSudokuException extends Exception {
- public InvalidSudokuException(String message) {
- super(message);
+/**
+ * Exception thrown when a trouble within the Sudoku board is determined.
+ * This exception typically indicates that the Sudoku board does not adhere
+ * to the rules of Sudoku, such as having duplicate numbers in rows, columns,
+ * or boxes.
+ *
+ *
+ * This exception extends {@link LocalizedModelException}, which provides
+ * support
+ * for localized error messages based on {@link ModelMessageKey}.
+ *
+ *
+ *
+ * The default error message is retrieved using the
+ * {@link ModelMessageKey#INVALID_SUDOKU_ERROR}
+ * key from the resource bundle.
+ *
+ *
+ *
+ * This exception can optionally wrap another throwable as its cause, providing
+ * additional context or information about the error.
+ *
+ *
+ * @see LocalizedModelException
+ * @see ModelMessageKey
+ */
+public class InvalidSudokuException extends LocalizedModelException {
+ /**
+ * Constructs a new InvalidSudokuException with a default error message key.
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#INVALID_SUDOKU_ERROR}.
+ */
+ public InvalidSudokuException() {
+ super(ModelMessageKey.INVALID_SUDOKU_ERROR);
+ }
+
+ /**
+ * Constructs a new InvalidSudokuException with the specified cause and
+ * a default error message key.
+ *
+ *
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#INVALID_SUDOKU_ERROR}.
+ *
+ *
+ * @param cause the cause of the exception
+ */
+ public InvalidSudokuException(Throwable cause) {
+ super(ModelMessageKey.INVALID_SUDOKU_ERROR, cause);
}
}
diff --git a/Model/src/main/java/sudoku/model/exceptions/LocalizedModelException.java b/Model/src/main/java/sudoku/model/exceptions/LocalizedModelException.java
new file mode 100644
index 0000000..3e9b478
--- /dev/null
+++ b/Model/src/main/java/sudoku/model/exceptions/LocalizedModelException.java
@@ -0,0 +1,44 @@
+package sudoku.model.exceptions;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * Represents a localized exception base class that can be thrown by the Model
+ * module.
+ * This exception is used to provide localized error messages to the user.
+ */
+public class LocalizedModelException extends RuntimeException {
+ /**
+ * Retrieves the localized message for the given message key.
+ *
+ * @param messageKey the key of the message to retrieve
+ * @return the localized message associated with the key
+ */
+ private static String getLocalizedMessage(String messageKey) {
+ ResourceBundle bundle = ResourceBundle.getBundle("ModelExceptions", Locale.getDefault());
+ return bundle.getString(messageKey);
+ }
+
+ /**
+ * Constructs a new LocalizedModelException with the specified messenger.
+ *
+ * @param messenger the ModelMessageKey representing the localized message
+ * key.
+ */
+ public LocalizedModelException(ModelMessageKey messenger) {
+ super(getLocalizedMessage(messenger.getKey()));
+ }
+
+ /**
+ * Constructs a new LocalizedModelException with the specified messenger and
+ * cause.
+ *
+ * @param messenger the ModelMessageKey representing the localized message
+ * key.
+ * @param cause the Throwable that caused this exception to be thrown.
+ */
+ public LocalizedModelException(ModelMessageKey messenger, Throwable cause) {
+ super(getLocalizedMessage(messenger.getKey()), cause);
+ }
+}
diff --git a/Model/src/main/java/sudoku/model/exceptions/ModelMessageKey.java b/Model/src/main/java/sudoku/model/exceptions/ModelMessageKey.java
new file mode 100644
index 0000000..801fac5
--- /dev/null
+++ b/Model/src/main/java/sudoku/model/exceptions/ModelMessageKey.java
@@ -0,0 +1,35 @@
+package sudoku.model.exceptions;
+
+/**
+ * Enumeration representing keys for localized error messages used in the Sudoku
+ * model.
+ * Each enum constant corresponds to a specific error message key for
+ * localization purposes.
+ */
+public enum ModelMessageKey {
+ VALIDATION_ERROR("VALIDATION_ERROR_MESSAGE_EXCEPTION"),
+ SUDOKU_FIELD_COMPARISON_ERROR("SUDOKU_FIELD_COMPARISON_ERROR_MESSAGE_EXCEPTION"),
+ INVALID_SUDOKU_ERROR("GENERAL_SUDOKU_ERROR_MESSAGE_EXCEPTION"),
+ FILLING_BOARD_ERROR("FILLING_BOARD_ERROR_MESSAGE_EXCEPTION");
+
+ private final String key;
+
+ /**
+ * Constructs a ModelMessageKey enum constant with the specified error message
+ * key.
+ *
+ * @param key the key representing the error message in localized resources
+ */
+ ModelMessageKey(String key) {
+ this.key = key;
+ }
+
+ /**
+ * Retrieves the error message key associated with this enum constant.
+ *
+ * @return the error message key
+ */
+ public String getKey() {
+ return key;
+ }
+}
diff --git a/Model/src/main/java/sudoku/model/exceptions/SudokuFieldComparisonException.java b/Model/src/main/java/sudoku/model/exceptions/SudokuFieldComparisonException.java
new file mode 100644
index 0000000..3f952f3
--- /dev/null
+++ b/Model/src/main/java/sudoku/model/exceptions/SudokuFieldComparisonException.java
@@ -0,0 +1,49 @@
+package sudoku.model.exceptions;
+
+/**
+ * Exception thrown when there is an error during comparison of Sudoku fields.
+ * This exception is typically used within the Sudoku model components to
+ * indicate
+ * errors encountered while comparing Sudoku fields.
+ *
+ *
+ * This exception extends {@link LocalizedModelException}, which provides
+ * support
+ * for localized error messages based on {@link ModelMessageKey}.
+ *
+ *
+ *
+ * Examples of comparison errors include unexpected null values or
+ * inconsistencies
+ * during the comparison of Sudoku fields.
+ *
+ *
+ * @see LocalizedModelException
+ * @see ModelMessageKey
+ */
+public class SudokuFieldComparisonException extends LocalizedModelException {
+ /**
+ * Constructs a new SudokuFieldComparisonException with a default error message
+ * key.
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#SUDOKU_FIELD_COMPARISON_ERROR}.
+ */
+ public SudokuFieldComparisonException() {
+ super(ModelMessageKey.SUDOKU_FIELD_COMPARISON_ERROR);
+ }
+
+ /**
+ * Constructs a new SudokuFieldComparisonException with the specified cause and
+ * a default error message key.
+ *
+ *
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#SUDOKU_FIELD_COMPARISON_ERROR}.
+ *
+ *
+ * @param cause the cause of the exception
+ */
+ public SudokuFieldComparisonException(Throwable cause) {
+ super(ModelMessageKey.SUDOKU_FIELD_COMPARISON_ERROR, cause);
+ }
+}
diff --git a/Model/src/main/java/sudoku/model/exceptions/ValidationSudokuException.java b/Model/src/main/java/sudoku/model/exceptions/ValidationSudokuException.java
new file mode 100644
index 0000000..f570d7a
--- /dev/null
+++ b/Model/src/main/java/sudoku/model/exceptions/ValidationSudokuException.java
@@ -0,0 +1,48 @@
+package sudoku.model.exceptions;
+
+/**
+ * Exception thrown when there is an error during validation of a Sudoku board.
+ * This exception is typically used within the Sudoku model components to
+ * indicate
+ * validation errors.
+ *
+ *
+ * This exception extends {@link LocalizedModelException}, which provides
+ * support
+ * for localized error messages based on {@link ModelMessageKey}.
+ *
+ *
+ *
+ * Examples of validation errors include incorrect Sudoku board configurations
+ * or
+ * failed validations during board operations.
+ *
+ *
+ * @see LocalizedModelException
+ * @see ModelMessageKey
+ */
+public class ValidationSudokuException extends LocalizedModelException {
+ /**
+ * Constructs a new ValidationSudokuException with a default error message key.
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#VALIDATION_ERROR}.
+ */
+ public ValidationSudokuException() {
+ super(ModelMessageKey.VALIDATION_ERROR);
+ }
+
+ /**
+ * Constructs a new ValidationSudokuException with the specified cause and
+ * a default error message key.
+ *
+ *
+ * The error message will be retrieved based on
+ * {@link ModelMessageKey#VALIDATION_ERROR}.
+ *
+ *
+ * @param cause the cause of the exception
+ */
+ public ValidationSudokuException(Throwable cause) {
+ super(ModelMessageKey.VALIDATION_ERROR, cause);
+ }
+}
diff --git a/Model/src/main/java/sudoku/model/interfaces/SudokuBaseContainer.java b/Model/src/main/java/sudoku/model/interfaces/SudokuBaseContainer.java
index dbb211e..1826221 100644
--- a/Model/src/main/java/sudoku/model/interfaces/SudokuBaseContainer.java
+++ b/Model/src/main/java/sudoku/model/interfaces/SudokuBaseContainer.java
@@ -2,22 +2,14 @@
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import sudoku.model.helpers.UniqueChecker;
import sudoku.model.models.SudokuBoard;
import sudoku.model.models.SudokuField;
import java.io.Serializable;
-import java.util.Locale;
-import java.util.ResourceBundle;
public class SudokuBaseContainer implements Verifiable, Serializable, Cloneable {
private SudokuField[] fields;
- private final Logger logger = LoggerFactory.getLogger(SudokuBaseContainer.class);
- private Locale locale = Locale.getDefault();
- private transient ResourceBundle exceptionsBundle = ResourceBundle
- .getBundle("sudoku.model.bundles.exceptions", locale);
public SudokuBaseContainer() {
fields = new SudokuField[SudokuBoard.BOARD_SIZE];
@@ -35,7 +27,6 @@ public boolean verify() {
try {
return UniqueChecker.checkUnique(fields);
} catch (IllegalArgumentException e) {
- logger.error(exceptionsBundle.getString("error.Verify"), e);
return false;
}
}
@@ -81,14 +72,6 @@ public SudokuBaseContainer clone() throws CloneNotSupportedException {
}
return clone;
// deep clone of SudokuBaseContainer using super.clone()
- // when using the clone method, cast the result to prefered implementation
- }
-
- public void setLocale(Locale locale) {
- this.locale = locale;
- exceptionsBundle = ResourceBundle.getBundle("sudoku.model.bundles.exceptions", locale);
- for (SudokuField field : fields) {
- field.setLocale(locale);
- }
+ // when using the clone method, cast the result to preferred implementation
}
}
diff --git a/Model/src/main/java/sudoku/model/models/SudokuBoard.java b/Model/src/main/java/sudoku/model/models/SudokuBoard.java
index 6e34b1c..3afcc91 100644
--- a/Model/src/main/java/sudoku/model/models/SudokuBoard.java
+++ b/Model/src/main/java/sudoku/model/models/SudokuBoard.java
@@ -5,7 +5,9 @@
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import sudoku.model.exceptions.InvalidSudokuException;
+
+import sudoku.model.exceptions.FillingBoardSudokuException;
+import sudoku.model.exceptions.ValidationSudokuException;
import sudoku.model.solver.BacktrackingSudokuSolver;
import sudoku.model.solver.SudokuSolver;
@@ -15,14 +17,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
public class SudokuBoard implements PropertyChangeListener, Serializable, Cloneable {
- Locale locale = Locale.getDefault();
private final Logger logger = LoggerFactory.getLogger(SudokuBoard.class);
- private transient ResourceBundle exceptionsBundle = ResourceBundle
- .getBundle("sudoku.model.bundles.exceptions", locale);
public static final int BOARD_SIZE = 9;
public static final int BOX_SIZE = 3;
@@ -97,7 +94,7 @@ public void setField(int x, int y, int value) {
SudokuField field = rows.get(y).getFields()[x];
field.setValue(value);
verifyBoard();
- } catch (InvalidSudokuException e) {
+ } catch (ValidationSudokuException e) {
logger.info("Invalid Sudoku board after setting field value");
}
}
@@ -123,7 +120,7 @@ public int getSize() {
return BOARD_SIZE;
}
- public void solveGame() throws InvalidSudokuException {
+ public void solveGame() throws FillingBoardSudokuException {
solver.solve(this);
}
@@ -146,9 +143,9 @@ public boolean isValidSudoku() {
return true;
}
- private void verifyBoard() throws InvalidSudokuException {
+ private void verifyBoard() throws ValidationSudokuException {
if (!isValidSudoku()) {
- throw new InvalidSudokuException(exceptionsBundle.getString("error.VerifyBoard"));
+ throw new ValidationSudokuException();
}
}
@@ -232,20 +229,4 @@ public SudokuBoard clone() throws CloneNotSupportedException {
return clone;
// deep clone of SudokuBoard using super.clone()
}
-
- public void changeLocale(Locale locale) {
- this.locale = locale;
- exceptionsBundle = ResourceBundle.getBundle("sudoku.model.bundles.exceptions", locale);
- for (SudokuRow row : rows) {
- row.setLocale(locale);
- }
-
- for (SudokuColumn column : columns) {
- column.setLocale(locale);
- }
-
- for (SudokuBox box : boxes) {
- box.setLocale(locale);
- }
- }
}
\ No newline at end of file
diff --git a/Model/src/main/java/sudoku/model/models/SudokuField.java b/Model/src/main/java/sudoku/model/models/SudokuField.java
index 89e103f..34c841a 100644
--- a/Model/src/main/java/sudoku/model/models/SudokuField.java
+++ b/Model/src/main/java/sudoku/model/models/SudokuField.java
@@ -4,20 +4,17 @@
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
+import sudoku.model.exceptions.SudokuFieldComparisonException;
+
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
public class SudokuField implements Serializable, Cloneable, Comparable {
private int value;
private List listeners;
- private Locale locale = Locale.getDefault();
- private transient ResourceBundle exceptionsBundle = ResourceBundle
- .getBundle("sudoku.model.bundles.exceptions", locale);
public SudokuField(int value) {
this.value = value;
@@ -56,8 +53,8 @@ protected void firePropertyChange(String propertyName, Object oldVal, Object new
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE)
- .append("value", value) // Assuming 'value' is your field value
- .toString();
+ .append("value", value)
+ .toString();
}
@Override
@@ -74,9 +71,9 @@ public boolean equals(Object obj) {
@Override
public int hashCode() {
- return new HashCodeBuilder(17,37)
- .append(value)
- .toHashCode();
+ return new HashCodeBuilder(17, 37)
+ .append(value)
+ .toHashCode();
}
@Override
@@ -90,13 +87,7 @@ public int compareTo(SudokuField o) {
try {
return Integer.compare(value, o.value);
} catch (NullPointerException e) {
- throw new NullPointerException(exceptionsBundle.getString("error.NullCompareTo"));
+ throw new SudokuFieldComparisonException(e);
}
- // compare the values of the fields
- }
-
- public void setLocale(Locale locale) {
- this.locale = locale;
- exceptionsBundle = ResourceBundle.getBundle("sudoku.model.bundles.exceptions", locale);
}
}
diff --git a/Model/src/main/java/sudoku/model/solver/BacktrackingSudokuSolver.java b/Model/src/main/java/sudoku/model/solver/BacktrackingSudokuSolver.java
index ae7896c..ba4e38d 100644
--- a/Model/src/main/java/sudoku/model/solver/BacktrackingSudokuSolver.java
+++ b/Model/src/main/java/sudoku/model/solver/BacktrackingSudokuSolver.java
@@ -1,29 +1,24 @@
package sudoku.model.solver;
-import sudoku.model.exceptions.InvalidSudokuException;
+import sudoku.model.exceptions.FillingBoardSudokuException;
import sudoku.model.models.SudokuBoard;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
public class BacktrackingSudokuSolver implements SudokuSolver {
final int sudokuBoardSize = SudokuBoard.BOARD_SIZE;
- Locale locale = Locale.getDefault();
- private transient ResourceBundle exceptionsBundle = ResourceBundle
- .getBundle("sudoku.model.bundles.exceptions", locale);
@Override
- public void solve(SudokuBoard board) throws InvalidSudokuException {
+ public void solve(SudokuBoard board) throws FillingBoardSudokuException {
fillBoard(board);
}
@Override
- public void fillBoard(SudokuBoard board) throws InvalidSudokuException {
+ public void fillBoard(SudokuBoard board) throws FillingBoardSudokuException {
if (!fillBoardRecursive(0, 0, board)) {
- throw new InvalidSudokuException(exceptionsBundle.getString("error.FillBoard"));
+ throw new FillingBoardSudokuException();
}
}
@@ -83,9 +78,4 @@ private boolean isValidPlacement(int row, int col, int num, SudokuBoard board) {
return validPlacement;
}
-
- public void setLocale(Locale locale) {
- this.locale = locale;
- exceptionsBundle = ResourceBundle.getBundle("sudoku.model.bundles.exceptions", locale);
- }
}
diff --git a/Model/src/main/java/sudoku/model/solver/SudokuSolver.java b/Model/src/main/java/sudoku/model/solver/SudokuSolver.java
index bab67fa..5bd5d54 100644
--- a/Model/src/main/java/sudoku/model/solver/SudokuSolver.java
+++ b/Model/src/main/java/sudoku/model/solver/SudokuSolver.java
@@ -1,13 +1,13 @@
package sudoku.model.solver;
-import sudoku.model.exceptions.InvalidSudokuException;
+import sudoku.model.exceptions.FillingBoardSudokuException;
import sudoku.model.models.SudokuBoard;
import java.io.Serializable;
public interface SudokuSolver extends Serializable {
- void fillBoard(SudokuBoard board) throws InvalidSudokuException;
+ void fillBoard(SudokuBoard board) throws FillingBoardSudokuException;
- void solve(SudokuBoard board) throws InvalidSudokuException;
+ void solve(SudokuBoard board) throws FillingBoardSudokuException;
}
diff --git a/Model/src/main/resources/ModelExceptions.properties b/Model/src/main/resources/ModelExceptions.properties
new file mode 100644
index 0000000..5be8dc0
--- /dev/null
+++ b/Model/src/main/resources/ModelExceptions.properties
@@ -0,0 +1,4 @@
+VALIDATION_ERROR_MESSAGE_EXCEPTION=Sudoku is not correctly solved
+FILLING_BOARD_ERROR_MESSAGE_EXCEPTION=Not able to properly fill Sudoku board with values
+SUDOKU_FIELD_COMPARISON_ERROR_MESSAGE_EXCEPTION=Not able to properly compare SudokuFields
+GENERAL_SUDOKU_ERROR_MESSAGE_EXCEPTION=Uh no, somethink went wrong within SudokuModel
\ No newline at end of file
diff --git a/Model/src/main/resources/ModelExceptions_pl_PL.properties b/Model/src/main/resources/ModelExceptions_pl_PL.properties
new file mode 100644
index 0000000..aed8276
--- /dev/null
+++ b/Model/src/main/resources/ModelExceptions_pl_PL.properties
@@ -0,0 +1,4 @@
+VALIDATION_ERROR_MESSAGE_EXCEPTION=Sudoku nie jest poprawnie rozwiązane
+FILLING_BOARD_ERROR_MESSAGE_EXCEPTION=Nie można prawidłowo wypełnić planszy Sudoku wartościami
+SUDOKU_FIELD_COMPARISON_ERROR_MESSAGE_EXCEPTION=Nie można prawidłowo porównać pól Sudoku
+GENERAL_SUDOKU_ERROR_MESSAGE_EXCEPTION=Ups, coś poszło nie tak z SudokuModel'em
\ No newline at end of file
diff --git a/Model/src/main/resources/sudoku/model/bundles/exceptions_en_EN.properties b/Model/src/main/resources/sudoku/model/bundles/exceptions_en_EN.properties
deleted file mode 100644
index 4f67fb9..0000000
--- a/Model/src/main/resources/sudoku/model/bundles/exceptions_en_EN.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-error.SetField=Unable to set Field value
-error.FillBoard=Not able to fill the Sudoku board
-error.Verify=Error while verifying uniqueness of fields
-error.NullCompareTo=Argument cannot be null
-error.VerifyBoard=Invalid Sudoku
\ No newline at end of file
diff --git a/Model/src/main/resources/sudoku/model/bundles/exceptions_pl_PL.properties b/Model/src/main/resources/sudoku/model/bundles/exceptions_pl_PL.properties
deleted file mode 100644
index 12506d5..0000000
--- a/Model/src/main/resources/sudoku/model/bundles/exceptions_pl_PL.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-error.SetField=Nie można ustawić wartości pola
-error.FillBoard=Nie można wypełnić planszy Sudoku
-error.Verify=Błąd podczas weryfikacji unikalności pól
-error.NullCompareTo=Argumrent nie może być nullem
-error.VerifyBoard=Nieprawidłowe Sudoku
\ No newline at end of file
diff --git a/Model/src/test/java/models/SudokuBoardTest.java b/Model/src/test/java/models/SudokuBoardTest.java
index 54bfa81..6a9b36f 100644
--- a/Model/src/test/java/models/SudokuBoardTest.java
+++ b/Model/src/test/java/models/SudokuBoardTest.java
@@ -6,6 +6,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
+import sudoku.model.exceptions.FillingBoardSudokuException;
import sudoku.model.exceptions.InvalidSudokuException;
import sudoku.model.models.SudokuBoard;
import sudoku.model.models.SudokuField;
@@ -19,7 +20,7 @@ void testFillBoardCorrectness() {
try {
sudokuBoard.solveGame();
- } catch (InvalidSudokuException e) {
+ } catch (FillingBoardSudokuException e) {
e.printStackTrace();
fail("solveGame() threw an InvalidSudokuException");
}
@@ -35,7 +36,7 @@ void testFillBoardSubsequentCalls() {
try {
sudokuBoard1.solveGame();
sudokuBoard2.solveGame();
- } catch (InvalidSudokuException e) {
+ } catch (FillingBoardSudokuException e) {
e.printStackTrace();
fail("solveGame() threw an InvalidSudokuException");
}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f4fc20b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,145 @@
+# Sudoku Java Desktop Application
+
+## Table of Contents
+
+- [Sudoku Java Desktop Application](#sudoku-java-desktop-application)
+ - [Table of Contents](#table-of-contents)
+ - [About the Project](#about-the-project)
+ - [In-Game Screenshots](#in-game-screenshots)
+ - [Main Menu](#main-menu)
+ - [Gameplay](#gameplay)
+ - [Save Game](#save-game)
+ - [Dependencies](#dependencies)
+ - [Installation](#installation)
+ - [How to Play](#how-to-play)
+ - [Features](#features)
+ - [Internationalization](#internationalization)
+ - [Database Schema](#database-schema)
+ - [Testing](#testing)
+
+## About the Project
+
+Multi-Module Maven project (MVC) of Sudoku Game with JavaFX GUI. The app provides the ability to choose different levels of difficulty, change the language, save to file, save to DB, and load the data from the file or from the DB. The game can be saved whenever a user wants to do it and save current progress to a file or DB and again load data to continue the started game in next session.
+
+## In-Game Screenshots
+
+### Main Menu
+
+
+
+
+
+
+
+
Main Menu ENG
+
Main Menu PL
+
+
+
+### Gameplay
+
+
+
+
+
+
+
+
Gameplay ENG
+
Gameplay PL
+
+
+
+### Save Game
+
+
+
+
+
+
+
+
Save Game DB
+
Save Game Filesystem
+
+
+
+## Dependencies
+
+This project requires the following dependencies:
+
+- Java >21: Minimum version required for running the application.
+- JDK >21: Minimum version required for running the application.
+- JavaFX >22: for building the graphical user interface.
+- Maven >3.9: for project management and building.
+- JOOQ: for database interactions.
+- SQLite: as the database to store Sudoku boards.
+- SLF4J and Logback: for logging purposes.
+
+## Installation
+
+To set up and run this project locally, follow these steps:
+
+1. **Clone the repository**:
+
+ ```sh
+ git clone https://github.com/Oskarowski/sudoku-desktop-game.git
+ cd sudoku-desktop-game
+ ```
+
+2. **Build the project**:
+
+ ```sh
+ mvn install
+ ```
+
+3. **Run the application**:
+ ```sh
+ mvn javafx:run -pl View
+ ```
+
+## How to Play
+
+1. **Start the Game**:
+
+ - Launch the application, choose difficulty and click on "New Game". Or load previous game from DB or filesystem.
+
+2. **Save Game**:
+
+ - Click on the "Save Game" button to save your current Sudoku board to a file.
+ - You can also save your game to a database by clicking the "Save to DB" button.
+
+3. **Load Game**:
+
+ - To load a game from a file, click on the "Load Game" button.
+ - To load a game from the database, first select the desired saved game from the list and next click on the "Load from DB" button and .
+
+4. **Solve Sudoku**:
+ - Fill in the cells with numbers from 1 to 9. Each number can appear only once per row, column, and 3x3 grid.
+
+## Features
+
+- **Save and Load Game**: Save your game progress to a file or database and load it anytime.
+- **Database Integration**: Store and retrieve Sudoku boards from DB (SQLite).
+- **System Filebase Integration**: Store and retrieve Sudoku boards using the system's filesystem (object serialization).
+- **Internationalization**: Supports multiple languages.
+- **User-friendly Interface**: Intuitive and easy-to-use GUI built with JavaFX.
+- **Difficulty Levels**: Choose from 3 different levels of difficulty.
+- **Logging**: Comprehensive logging for debugging.
+
+## Internationalization
+
+This application supports currently English and Polish languages. The localization is handled using `ResourceBundle` to load the appropriate language properties files based on the user's locale.
+
+## Database Schema
+
+The Sudoku game uses a **SQLite** database to store game boards and fields.
+
+For an ER diagram illustrating the database schema, please refer to [ER Diagram](JdbcDao/src/main/java/sudoku/jdbcdao/database/database-schema.md).
+
+## Testing
+
+This project uses **JUnit Jupiter** for unit tests and **JaCoCo** for code coverage analysis.
+ To execute the tests, run:
+
+```sh
+mvn test
+```
diff --git a/View/preview-screenshots/game_screen_en.png b/View/preview-screenshots/game_screen_en.png
new file mode 100644
index 0000000..d7927c4
Binary files /dev/null and b/View/preview-screenshots/game_screen_en.png differ
diff --git a/View/preview-screenshots/game_screen_pl.png b/View/preview-screenshots/game_screen_pl.png
new file mode 100644
index 0000000..d131a55
Binary files /dev/null and b/View/preview-screenshots/game_screen_pl.png differ
diff --git a/View/preview-screenshots/main_menu_screen_en.png b/View/preview-screenshots/main_menu_screen_en.png
new file mode 100644
index 0000000..cc665ac
Binary files /dev/null and b/View/preview-screenshots/main_menu_screen_en.png differ
diff --git a/View/preview-screenshots/main_menu_screen_pl.png b/View/preview-screenshots/main_menu_screen_pl.png
new file mode 100644
index 0000000..7434f24
Binary files /dev/null and b/View/preview-screenshots/main_menu_screen_pl.png differ
diff --git a/View/preview-screenshots/save_game_db_en.png b/View/preview-screenshots/save_game_db_en.png
new file mode 100644
index 0000000..ded587d
Binary files /dev/null and b/View/preview-screenshots/save_game_db_en.png differ
diff --git a/View/preview-screenshots/save_game_filesystem_en.png b/View/preview-screenshots/save_game_filesystem_en.png
new file mode 100644
index 0000000..bc5c08f
Binary files /dev/null and b/View/preview-screenshots/save_game_filesystem_en.png differ
diff --git a/View/src/main/java/sudoku/view/App.java b/View/src/main/java/sudoku/view/App.java
index ecdeae3..66b05db 100644
--- a/View/src/main/java/sudoku/view/App.java
+++ b/View/src/main/java/sudoku/view/App.java
@@ -4,6 +4,7 @@
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
+import javafx.scene.image.Image;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,6 +25,7 @@ public void start(Stage stage) throws IOException {
ResourceBundle resourceBundle = LanguageEnum.getResourceBundle();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/sudoku/view/MainMenu.fxml"), resourceBundle);
+ Image icon = new Image(getClass().getResourceAsStream("/icons/favicon.png"));
MainMenuController mainMenuController = new MainMenuController();
loader.setController(mainMenuController);
@@ -33,6 +35,7 @@ public void start(Stage stage) throws IOException {
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sudoku Game");
primaryStage.show();
+ primaryStage.getIcons().add(icon);
}
static void setScene(Parent newRoot) {
@@ -42,5 +45,4 @@ static void setScene(Parent newRoot) {
public static void main(String[] args) {
launch();
}
-
}
\ No newline at end of file
diff --git a/View/src/main/java/sudoku/view/GameController.java b/View/src/main/java/sudoku/view/GameController.java
index c356021..14ed4b2 100644
--- a/View/src/main/java/sudoku/view/GameController.java
+++ b/View/src/main/java/sudoku/view/GameController.java
@@ -8,28 +8,23 @@
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
-import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
-import javafx.stage.DirectoryChooser;
+import javafx.stage.Stage;
import javafx.util.converter.IntegerStringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import sudoku.dao.exceptions.SudokuReadException;
-import sudoku.dao.factories.SudokuBoardDaoFactory;
-import sudoku.dao.interfaces.Dao;
-import sudoku.jdbcdao.JdbcSudokuBoardDao;
-import sudoku.model.exceptions.InvalidSudokuException;
+import sudoku.model.exceptions.FillingBoardSudokuException;
import sudoku.model.models.SudokuBoard;
import sudoku.model.models.SudokuField;
import sudoku.model.solver.BacktrackingSudokuSolver;
+import sudoku.view.strategies.SaveSudokuBoardStrategy;
+import sudoku.view.strategies.SaveSudokuBoardToDatabaseStrategy;
+import sudoku.view.strategies.SaveSudokuBoardToFileStrategy;
-import java.io.File;
import java.net.URL;
-import java.nio.file.Paths;
-import java.util.Optional;
import java.util.ResourceBundle;
public class GameController implements Initializable {
@@ -64,15 +59,15 @@ public GameController(DifficultyEnum initialGameDifficulty, SudokuBoard sudokuBo
public void initialize(URL location, ResourceBundle resources) {
logger.info("Sudoku Game Controller Initialized");
- saveGameToFileButton.setOnAction(event -> saveSudokuGameToFile());
- saveGameToDatabaseButton.setOnAction(event -> saveSudokuGameToDatabase());
+ saveGameToFileButton.setOnAction(event -> saveSudokuGame(new SaveSudokuBoardToFileStrategy()));
+ saveGameToDatabaseButton.setOnAction(event -> saveSudokuGame(new SaveSudokuBoardToDatabaseStrategy()));
if (sudokuBoard == null) {
sudokuBoard = new SudokuBoard(new BacktrackingSudokuSolver());
try {
sudokuBoard.solveGame();
- } catch (InvalidSudokuException e) {
+ } catch (FillingBoardSudokuException e) {
e.printStackTrace();
}
@@ -137,7 +132,6 @@ public String toString(Integer value) {
if (!newValue.matches("[0-9]?")) {
textField.setText(oldValue);
} else {
- logger.info("New Value: " + newValue);
sudokuField.setValue(newValue.isEmpty() ? 0 : Integer.parseInt(newValue));
if (sudokuBoard.checkEndGame()) {
@@ -162,83 +156,12 @@ private void endGame() {
}
}
- private void saveSudokuGameToFile() {
- logger.info("Try To Save Sudoku Game");
-
- try {
- DirectoryChooser directoryChooser = new DirectoryChooser();
- directoryChooser.setTitle("Choose Where To Save Sudoku Board");
-
- File selectedDirectory = directoryChooser.showDialog(saveGameToFileButton.getScene().getWindow());
-
- if (selectedDirectory != null) {
- logger.info("Directory Path: " + selectedDirectory);
-
- // Prompt the user to enter the filename under which to save the Sudoku board
- TextInputDialog dialog = new TextInputDialog();
- dialog.setTitle("Enter File Name");
- dialog.setHeaderText("Please enter the name for the Sudoku board file:");
- dialog.setContentText("File Name:");
-
- Optional result = dialog.showAndWait();
-
- if (result.isEmpty()) {
- return;
- }
-
- String fileName = result.get();
- logger.info("File Name: " + fileName);
-
- Dao sudokuBoardDao = SudokuBoardDaoFactory
- .createSudokuBoardDao(selectedDirectory.toString());
-
- sudokuBoardDao.write(fileName, this.sudokuBoard);
- }
- } catch (SudokuReadException e) {
- logger.error("Error occurred while saving sudoku board to file");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void saveSudokuGameToDatabase() {
- logger.info("Try To Save Sudoku Game In Database");
-
+ private void saveSudokuGame(SaveSudokuBoardStrategy strategy) {
+ Stage stage = (Stage) saveGameToFileButton.getScene().getWindow(); // Or any node to get the window
try {
- // Prompt the user to enter the name under which to save the Sudoku board
- TextInputDialog dialog = new TextInputDialog();
- dialog.setTitle("Enter Game Name");
- dialog.setHeaderText("Please enter the name for the Sudoku board game:");
- dialog.setContentText("Game Name:");
-
- Optional result = dialog.showAndWait();
-
- if (result.isEmpty()) {
- return;
- }
-
- // Path to the database file in JdbcDaoProject directory
- String jdbcDaoProjectPath = Paths.get("..", "JdbcDao", "sudoku.db").toString();
- String databaseFilePath = Paths.get(jdbcDaoProjectPath).toAbsolutePath().toString();
-
- String gameName = result.get();
- logger.info("Game Name: " + gameName);
-
- try (Dao sudokuBoardDao = SudokuBoardDaoFactory.createJdbcSudokuBoardDao(databaseFilePath)) {
- if(!(sudokuBoardDao instanceof JdbcSudokuBoardDao)){
- logger.error("sudokuBoardDao is not instance of JdbcSudokuBoardDao");
- throw new Error("sudokuBoardDao is not instance of JdbcSudokuBoardDao");
- }
-
- sudokuBoardDao.write(gameName, this.sudokuBoard);
- logger.info("Sudoku board saved to database with name: " + gameName);
- } catch (Exception e) {
- logger.error("Error occurred while saving sudoku board to database", e);
- throw e;
- }
+ strategy.save(sudokuBoard, stage);
} catch (Exception e) {
- e.printStackTrace();
- logger.error("Unexpected error occurred E90235", e);
+ logger.error("Failed to save the SudokuBoard", e);
}
}
}
diff --git a/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardStrategy.java b/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardStrategy.java
new file mode 100644
index 0000000..375aba5
--- /dev/null
+++ b/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardStrategy.java
@@ -0,0 +1,34 @@
+package sudoku.view.strategies;
+
+import java.util.Optional;
+
+import javafx.scene.control.TextInputDialog;
+import javafx.stage.Window;
+
+import sudoku.model.models.SudokuBoard;
+
+public abstract class SaveSudokuBoardStrategy {
+ /**
+ * Perform a save operation for the given Sudoku board.
+ *
+ * @param sudokuBoard the SudokuBoard to be saved
+ * @param ownerWindow the owner window of the save operation
+ */
+ public abstract void save(SudokuBoard sudokuBoard, Window ownerWindow);
+
+ /**
+ * Prompts the user to enter a name for the SudokuBoard game.
+ *
+ * @param ownerWindow the owner window of the prompt
+ * @return an Optional containing the entered name, or an empty Optional if the
+ * user cancels the prompt, or don't provide a name
+ */
+ protected Optional promptForSudokuBoardName(Window ownerWindow) {
+ TextInputDialog dialog = new TextInputDialog();
+ dialog.setTitle("Enter Sudoku Board Name");
+ dialog.setHeaderText("Please enter the name for the SudokuBoard game:");
+ dialog.setContentText("Game name:");
+
+ return dialog.showAndWait();
+ }
+}
diff --git a/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardToDatabaseStrategy.java b/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardToDatabaseStrategy.java
new file mode 100644
index 0000000..fe883d8
--- /dev/null
+++ b/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardToDatabaseStrategy.java
@@ -0,0 +1,54 @@
+package sudoku.view.strategies;
+
+import java.nio.file.Paths;
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javafx.stage.Window;
+import sudoku.dao.factories.SudokuBoardDaoFactory;
+import sudoku.dao.interfaces.Dao;
+import sudoku.jdbcdao.JdbcSudokuBoardDao;
+import sudoku.model.models.SudokuBoard;
+
+public class SaveSudokuBoardToDatabaseStrategy extends SaveSudokuBoardStrategy {
+ private static final Logger logger = LoggerFactory.getLogger(SaveSudokuBoardToDatabaseStrategy.class);
+
+ @Override
+ public void save(SudokuBoard sudokuBoard, Window ownerWindow) {
+ logger.info("Try To Save Sudoku Game to Database");
+
+ try {
+ // Prompt the user to enter the filename under which to save the SudokuBoard
+ Optional result = this.promptForSudokuBoardName(ownerWindow);
+
+ if (result.isEmpty()) {
+ return;
+ }
+
+ // Path to the database file in JdbcDaoProject directory
+ String jdbcDaoProjectPath = Paths.get("..", "JdbcDao", "sudoku.db").toString();
+ String databaseFilePath = Paths.get(jdbcDaoProjectPath).toAbsolutePath().toString();
+
+ String gameName = result.get();
+ logger.info("Game Name: " + gameName);
+
+ try (Dao sudokuBoardDao = SudokuBoardDaoFactory.createJdbcSudokuBoardDao(databaseFilePath)) {
+ if (!(sudokuBoardDao instanceof JdbcSudokuBoardDao)) {
+ logger.error("sudokuBoardDao is not instance of JdbcSudokuBoardDao");
+ throw new Error("sudokuBoardDao is not instance of JdbcSudokuBoardDao");
+ }
+
+ sudokuBoardDao.write(gameName, sudokuBoard);
+ logger.info("Sudoku Board saved to DB with name: " + gameName);
+ } catch (Exception e) {
+ logger.error("Error occurred while saving sudoku board to DB", e);
+ throw e;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("Unexpected error occurred E90235", e);
+ }
+ }
+}
diff --git a/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardToFileStrategy.java b/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardToFileStrategy.java
new file mode 100644
index 0000000..8abb6bc
--- /dev/null
+++ b/View/src/main/java/sudoku/view/strategies/SaveSudokuBoardToFileStrategy.java
@@ -0,0 +1,55 @@
+package sudoku.view.strategies;
+
+import javafx.stage.DirectoryChooser;
+import javafx.stage.Window;
+import sudoku.dao.exceptions.SudokuReadException;
+import sudoku.dao.factories.SudokuBoardDaoFactory;
+import sudoku.dao.interfaces.Dao;
+import sudoku.model.models.SudokuBoard;
+
+import java.io.File;
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SaveSudokuBoardToFileStrategy extends SaveSudokuBoardStrategy {
+ private static final Logger logger = LoggerFactory.getLogger(SaveSudokuBoardToFileStrategy.class);
+
+ @Override
+ public void save(SudokuBoard sudokuBoard, Window ownerWindow) {
+ logger.info("Try To Save SudokuBoard to File");
+
+ try {
+ DirectoryChooser directoryChooser = new DirectoryChooser();
+ directoryChooser.setTitle("Choose Where To Save Sudoku Board");
+
+ File selectedDirectory = directoryChooser.showDialog(ownerWindow);
+
+ if (selectedDirectory == null) {
+ return;
+ }
+
+ logger.info("Directory Path selected to be saved into: " + selectedDirectory);
+
+ // Prompt the user to enter the filename under which to save the SudokuBoard
+ Optional result = this.promptForSudokuBoardName(ownerWindow);
+
+ if (result.isEmpty()) {
+ return;
+ }
+
+ String fileName = result.get();
+ logger.info("File name under which to save Sudoku Board: " + fileName);
+
+ Dao sudokuBoardDao = SudokuBoardDaoFactory
+ .createSudokuBoardDao(selectedDirectory.toString());
+
+ sudokuBoardDao.write(fileName, sudokuBoard);
+ } catch (SudokuReadException e) {
+ logger.error("Error occurred while saving Sudoku Board to file");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/View/src/main/resources/icons/database-solid.png b/View/src/main/resources/icons/database-solid.png
new file mode 100644
index 0000000..ff9d69a
Binary files /dev/null and b/View/src/main/resources/icons/database-solid.png differ
diff --git a/View/src/main/resources/icons/database-solid.svg b/View/src/main/resources/icons/database-solid.svg
new file mode 100644
index 0000000..2218f6a
--- /dev/null
+++ b/View/src/main/resources/icons/database-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/View/src/main/resources/icons/favicon.png b/View/src/main/resources/icons/favicon.png
new file mode 100644
index 0000000..cb7377c
Binary files /dev/null and b/View/src/main/resources/icons/favicon.png differ
diff --git a/View/src/main/resources/icons/floppy-disk-solid.png b/View/src/main/resources/icons/floppy-disk-solid.png
new file mode 100644
index 0000000..d277d41
Binary files /dev/null and b/View/src/main/resources/icons/floppy-disk-solid.png differ
diff --git a/View/src/main/resources/icons/floppy-disk-solid.svg b/View/src/main/resources/icons/floppy-disk-solid.svg
new file mode 100644
index 0000000..69b2ef5
--- /dev/null
+++ b/View/src/main/resources/icons/floppy-disk-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/View/src/main/resources/icons/language-solid.png b/View/src/main/resources/icons/language-solid.png
new file mode 100644
index 0000000..da39328
Binary files /dev/null and b/View/src/main/resources/icons/language-solid.png differ
diff --git a/View/src/main/resources/icons/language-solid.svg b/View/src/main/resources/icons/language-solid.svg
new file mode 100644
index 0000000..83ccc47
--- /dev/null
+++ b/View/src/main/resources/icons/language-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/View/src/main/resources/icons/play-solid.png b/View/src/main/resources/icons/play-solid.png
new file mode 100644
index 0000000..61f07cd
Binary files /dev/null and b/View/src/main/resources/icons/play-solid.png differ
diff --git a/View/src/main/resources/icons/play-solid.svg b/View/src/main/resources/icons/play-solid.svg
new file mode 100644
index 0000000..2bc6ded
--- /dev/null
+++ b/View/src/main/resources/icons/play-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/View/src/main/resources/icons/right-from-bracket-solid.png b/View/src/main/resources/icons/right-from-bracket-solid.png
new file mode 100644
index 0000000..afe8447
Binary files /dev/null and b/View/src/main/resources/icons/right-from-bracket-solid.png differ
diff --git a/View/src/main/resources/icons/right-from-bracket-solid.svg b/View/src/main/resources/icons/right-from-bracket-solid.svg
new file mode 100644
index 0000000..1b6b971
--- /dev/null
+++ b/View/src/main/resources/icons/right-from-bracket-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/View/src/main/resources/sudoku/view/MainMenu.fxml b/View/src/main/resources/sudoku/view/MainMenu.fxml
index 9b072f4..26e1646 100644
--- a/View/src/main/resources/sudoku/view/MainMenu.fxml
+++ b/View/src/main/resources/sudoku/view/MainMenu.fxml
@@ -6,6 +6,8 @@
+
+
@@ -17,7 +19,7 @@
-
-
+
-
-
+
+
-
+
\ No newline at end of file
diff --git a/View/src/main/resources/sudoku/view/bundles/en_EN.properties b/View/src/main/resources/sudoku/view/bundles/en_EN.properties
index 571ea1d..4e9ad1b 100644
--- a/View/src/main/resources/sudoku/view/bundles/en_EN.properties
+++ b/View/src/main/resources/sudoku/view/bundles/en_EN.properties
@@ -3,7 +3,7 @@ DIFFICULTY_LEVEL=Difficulty Level
EASY_DIFFICULTY=Easy
MEDIUM_DIFFICULTY=Medium
HARD_DIFFICULTY=Hard
-START_GAME=Start Game
+START_GAME=New Game
EXIT_GAME=Exit Game
LOAD_GAME=Load Game
SAVE_GAME_TO_FILE=Save Game
diff --git a/View/src/main/resources/sudoku/view/bundles/pl_PL.properties b/View/src/main/resources/sudoku/view/bundles/pl_PL.properties
index 757cfe6..698deec 100644
--- a/View/src/main/resources/sudoku/view/bundles/pl_PL.properties
+++ b/View/src/main/resources/sudoku/view/bundles/pl_PL.properties
@@ -3,9 +3,9 @@ DIFFICULTY_LEVEL=Poziom trudności
EASY_DIFFICULTY=Łatwy
MEDIUM_DIFFICULTY=Średni
HARD_DIFFICULTY=Trudny
-START_GAME=Rozpocznij grę
+START_GAME=Nowa gra
EXIT_GAME=Wyjdź z gry
LOAD_GAME=Wczytaj grę
SAVE_GAME_TO_FILE=Zapisz grę
-SAVE_GAME_TO_DATABASE=Zapis do DB
+SAVE_GAME_TO_DATABASE=Zapisz do DB
LOAD_GAME_FROM_DB=Wczytaj z DB
\ No newline at end of file