diff --git a/pom.xml b/pom.xml index 3de4cfb..8244b25 100644 --- a/pom.xml +++ b/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 org.toop @@ -12,9 +12,9 @@ 24 24 - UTF-8 + UTF-8 - org.toop.Main + org.toop.Main @@ -177,4 +177,4 @@ - + \ No newline at end of file diff --git a/src/main/java/org/toop/Logging.java b/src/main/java/org/toop/Logging.java deleted file mode 100644 index c44d09f..0000000 --- a/src/main/java/org/toop/Logging.java +++ /dev/null @@ -1,201 +0,0 @@ -package org.toop; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.LoggerConfig; - -/** - * Utility class for configuring logging levels dynamically at runtime using Log4j 2. - * - *

Provides methods to enable or disable logs globally or per class, with support for specifying - * log levels either via {@link Level} enums or string names. - */ -public final class Logging { - - /** Disables all logging globally by setting the root logger level to {@link Level#OFF}. */ - public static void disableAllLogs() { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - LoggerConfig rootLoggerConfig = config.getRootLogger(); - rootLoggerConfig.setLevel(Level.OFF); - ctx.updateLoggers(); - } - - /** Enables all logging globally by setting the root logger level to {@link Level#ALL}. */ - public static void enableAllLogs() { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - LoggerConfig rootLoggerConfig = config.getRootLogger(); - rootLoggerConfig.setLevel(Level.ALL); - ctx.updateLoggers(); - } - - /** - * Enables global logging at a specific level by setting the root logger. - * - * @param level the logging level to enable for all logs - */ - public static void enableAllLogs(Level level) { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - LoggerConfig rootLoggerConfig = config.getRootLogger(); - rootLoggerConfig.setLevel(level); - ctx.updateLoggers(); - } - - /** - * Verifies whether the provided string corresponds to a valid class name. - * - * @param className fully-qualified class name to check - * @return true if the class exists, false otherwise - */ - private static boolean verifyStringIsActualClass(String className) { - try { - Class.forName(className); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - - /** - * Internal helper to disable logs for a specific class by name. - * - * @param className fully-qualified class name - */ - private static void disableLogsForClassInternal(String className) { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - config.removeLogger(className); - LoggerConfig specificConfig = new LoggerConfig(className, Level.OFF, false); - config.addLogger(className, specificConfig); - ctx.updateLoggers(); - } - - /** - * Disables logs for a specific class. - * - * @param class_ the class for which logs should be disabled - * @param type of the class - */ - public static void disableLogsForClass(Class class_) { - disableLogsForClassInternal(class_.getName()); - } - - /** - * Disables logs for a class specified by fully-qualified name, if the class exists. - * - * @param className fully-qualified class name - */ - public static void disableLogsForClass(String className) { - if (verifyStringIsActualClass(className)) { - disableLogsForClassInternal(className); - } - } - - /** - * Internal helper to enable logs for a specific class at a specific level. - * - * @param className fully-qualified class name - * @param level logging level to set - */ - private static void enableLogsForClassInternal(String className, Level level) { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - LoggerConfig loggerConfig = config.getLoggers().get(className); - if (loggerConfig == null) { - loggerConfig = new LoggerConfig(className, level, false); - config.addLogger(className, loggerConfig); - } else { - loggerConfig.setLevel(level); - } - ctx.updateLoggers(); - } - - /** - * Enables logging for a class at a specific level. - * - * @param class_ class to configure - * @param levelToLog the logging level to set - * @param type of the class - */ - public static void enableLogsForClass(Class class_, Level levelToLog) { - enableLogsForClassInternal(class_.getName(), levelToLog); - } - - /** - * Enables logging for a class specified by name at a specific level, if the class exists. - * - * @param className fully-qualified class name - * @param levelToLog the logging level to set - */ - public static void enableLogsForClass(String className, Level levelToLog) { - if (verifyStringIsActualClass(className)) { - enableLogsForClassInternal(className, levelToLog); - } - } - - /** - * Enables logging for a class specified by name at a specific level using a string. - * - * @param className fully-qualified class name - * @param levelToLog name of the logging level (e.g., "DEBUG", "INFO") - */ - public static void enableLogsForClass(String className, String levelToLog) { - Level level = Level.valueOf(levelToLog.trim().toUpperCase()); - if (level != null && verifyStringIsActualClass(className)) { - enableLogsForClassInternal(className, level); - } - } - - /** Convenience methods for enabling logs at specific levels for classes. */ - public static void enableAllLogsForClass(Class class_) { - enableLogsForClass(class_, Level.ALL); - } - - public static void enableAllLogsForClass(String className) { - enableLogsForClass(className, Level.ALL); - } - - public static void enableDebugLogsForClass(Class class_) { - enableLogsForClass(class_, Level.DEBUG); - } - - public static void enableDebugLogsForClass(String className) { - enableLogsForClass(className, Level.DEBUG); - } - - public static void enableErrorLogsForClass(Class class_) { - enableLogsForClass(class_, Level.ERROR); - } - - public static void enableErrorLogsForClass(String className) { - enableLogsForClass(className, Level.ERROR); - } - - public static void enableFatalLogsForClass(Class class_) { - enableLogsForClass(class_, Level.FATAL); - } - - public static void enableFatalLogsForClass(String className) { - enableLogsForClass(className, Level.FATAL); - } - - public static void enableInfoLogsForClass(Class class_) { - enableLogsForClass(class_, Level.INFO); - } - - public static void enableInfoLogsForClass(String className) { - enableLogsForClass(className, Level.INFO); - } - - public static void enableTraceLogsForClass(Class class_) { - enableLogsForClass(class_, Level.TRACE); - } - - public static void enableTraceLogsForClass(String className) { - enableLogsForClass(className, Level.TRACE); - } -} diff --git a/src/main/java/org/toop/Main.java b/src/main/java/org/toop/Main.java index 52830ed..e64efec 100644 --- a/src/main/java/org/toop/Main.java +++ b/src/main/java/org/toop/Main.java @@ -1,62 +1,6 @@ package org.toop; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.toop.backend.tictactoe.ServerManager; -import org.toop.eventbus.EventPublisher; -import org.toop.eventbus.events.Events; -import org.toop.eventbus.GlobalEventBus; -import org.toop.frontend.UI.LocalServerSelector; -import org.toop.frontend.networking.NetworkingClientManager; - public class Main { - private static final Logger logger = LogManager.getLogger(Main.class); - private static boolean running = false; - - public static void main(String[] args) throws ExecutionException, InterruptedException { - // Logging.disableAllLogs(); - Logging.enableAllLogsForClass(EventRegistry.class); - // Logging.enableLogsForClass(ServerManager.class, Level.ALL); - // Logging.enableLogsForClass(TicTacToeServer.class, Level.ALL); - // Logging.enableLogsForClass(TcpClient.class, Level.ALL); - // Logging.enableLogsForClass(NetworkingClientManager.class, Level.ALL); - - initSystems(); - registerEvents(); - - CompletableFuture serverIdFuture = new CompletableFuture<>(); - GlobalEventBus.post( - new Events.ServerEvents.StartServerRequest(5001, "tictactoe", serverIdFuture)); - var serverId = serverIdFuture.get(); - - var a = new MainTest(); - - javax.swing.SwingUtilities.invokeLater(LocalServerSelector::new); - - } - - private static void initSystems() { - new ServerManager(); - new NetworkingClientManager(); - } - - private static void registerEvents() { - new EventPublisher().onEvent(Events.WindowEvents.OnQuitRequested.class).perform(_ -> quit()); - new EventPublisher().onEvent(Events.WindowEvents.OnMouseMove.class).perform(_ -> {}); - } - - private static void quit() { - running = false; - } - - public static boolean isRunning() { - return running; - } - - public static void setRunning(boolean running) { - Main.running = running; - } -} + public static void main(String[] args) { + } +} \ No newline at end of file diff --git a/src/main/java/org/toop/app/GameBase.java b/src/main/java/org/toop/app/GameBase.java new file mode 100644 index 0000000..46e1832 --- /dev/null +++ b/src/main/java/org/toop/app/GameBase.java @@ -0,0 +1,57 @@ +package org.toop.app; + +// Todo: refactor +public abstract class GameBase { + public enum State { + INVALID, + + NORMAL, + DRAW, + WIN, + } + + public static char EMPTY = '-'; + + protected int size; + public char[] grid; + + protected Player[] players; + public int currentPlayer; + + public GameBase(int size, Player player1, Player player2) { + this.size = size; + grid = new char[size * size]; + + for (int i = 0; i < grid.length; i++) { + grid[i] = EMPTY; + } + + players = new Player[2]; + players[0] = player1; + players[1] = player2; + + currentPlayer = 0; + } + + public boolean isInside(int index) { + return index >= 0 && index < size * size; + } + + public int getSize() { + return size; + } + + public char[] getGrid() { + return grid; + } + + public Player[] getPlayers() { + return players; + } + + public Player getCurrentPlayer() { + return players[currentPlayer]; + } + + public abstract State play(int index); +} \ No newline at end of file diff --git a/src/main/java/org/toop/app/Player.java b/src/main/java/org/toop/app/Player.java new file mode 100644 index 0000000..137c05b --- /dev/null +++ b/src/main/java/org/toop/app/Player.java @@ -0,0 +1,20 @@ +package org.toop.app; + +// Todo: refactor +public class Player { + String name; + char symbol; + + Player(String name, char symbol) { + this.name = name; + this.symbol = symbol; + } + + public String getName() { + return this.name; + } + + public char getSymbol() { + return this.symbol; + } +} \ No newline at end of file diff --git a/src/main/java/org/toop/frontend/UI/BackgroundPanel.java b/src/main/java/org/toop/app/gui/BackgroundPanel.java similarity index 94% rename from src/main/java/org/toop/frontend/UI/BackgroundPanel.java rename to src/main/java/org/toop/app/gui/BackgroundPanel.java index 23cb0ce..bd5c6d2 100644 --- a/src/main/java/org/toop/frontend/UI/BackgroundPanel.java +++ b/src/main/java/org/toop/app/gui/BackgroundPanel.java @@ -1,4 +1,4 @@ -package org.toop.frontend.UI; +package org.toop.app.gui; import java.awt.*; import javax.swing.*; diff --git a/src/main/java/org/toop/frontend/UI/LocalGameSelector.form b/src/main/java/org/toop/app/gui/LocalGameSelector.form similarity index 96% rename from src/main/java/org/toop/frontend/UI/LocalGameSelector.form rename to src/main/java/org/toop/app/gui/LocalGameSelector.form index d9f3f18..0816519 100644 --- a/src/main/java/org/toop/frontend/UI/LocalGameSelector.form +++ b/src/main/java/org/toop/app/gui/LocalGameSelector.form @@ -1,5 +1,5 @@ -

+ diff --git a/src/main/java/org/toop/frontend/UI/LocalGameSelector.java b/src/main/java/org/toop/app/gui/LocalGameSelector.java similarity index 96% rename from src/main/java/org/toop/frontend/UI/LocalGameSelector.java rename to src/main/java/org/toop/app/gui/LocalGameSelector.java index 524b10b..ff11be8 100644 --- a/src/main/java/org/toop/frontend/UI/LocalGameSelector.java +++ b/src/main/java/org/toop/app/gui/LocalGameSelector.java @@ -1,10 +1,11 @@ -package org.toop.frontend.UI; +package org.toop.app.gui; import java.awt.*; import javax.swing.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.toop.frontend.games.LocalTicTacToe; +import org.toop.app.tictactoe.LocalTicTacToe; +import org.toop.app.tictactoe.gui.UIGameBoard; public class LocalGameSelector extends JFrame { private static final Logger logger = LogManager.getLogger(LocalGameSelector.class); diff --git a/src/main/java/org/toop/frontend/UI/LocalServerSelector.form b/src/main/java/org/toop/app/gui/LocalServerSelector.form similarity index 96% rename from src/main/java/org/toop/frontend/UI/LocalServerSelector.form rename to src/main/java/org/toop/app/gui/LocalServerSelector.form index 73dbbb4..68623a2 100644 --- a/src/main/java/org/toop/frontend/UI/LocalServerSelector.form +++ b/src/main/java/org/toop/app/gui/LocalServerSelector.form @@ -1,5 +1,5 @@ - + diff --git a/src/main/java/org/toop/frontend/UI/LocalServerSelector.java b/src/main/java/org/toop/app/gui/LocalServerSelector.java similarity index 96% rename from src/main/java/org/toop/frontend/UI/LocalServerSelector.java rename to src/main/java/org/toop/app/gui/LocalServerSelector.java index b09f461..50eb60b 100644 --- a/src/main/java/org/toop/frontend/UI/LocalServerSelector.java +++ b/src/main/java/org/toop/app/gui/LocalServerSelector.java @@ -1,4 +1,4 @@ -package org.toop.frontend.UI; +package org.toop.app.gui; import javax.swing.*; diff --git a/src/main/java/org/toop/frontend/UI/RemoteGameSelector.form b/src/main/java/org/toop/app/gui/RemoteGameSelector.form similarity index 99% rename from src/main/java/org/toop/frontend/UI/RemoteGameSelector.form rename to src/main/java/org/toop/app/gui/RemoteGameSelector.form index 1bb35ab..df43ead 100644 --- a/src/main/java/org/toop/frontend/UI/RemoteGameSelector.form +++ b/src/main/java/org/toop/app/gui/RemoteGameSelector.form @@ -1,5 +1,5 @@ - + diff --git a/src/main/java/org/toop/frontend/UI/RemoteGameSelector.java b/src/main/java/org/toop/app/gui/RemoteGameSelector.java similarity index 95% rename from src/main/java/org/toop/frontend/UI/RemoteGameSelector.java rename to src/main/java/org/toop/app/gui/RemoteGameSelector.java index dfc0d2e..de8e869 100644 --- a/src/main/java/org/toop/frontend/UI/RemoteGameSelector.java +++ b/src/main/java/org/toop/app/gui/RemoteGameSelector.java @@ -1,4 +1,4 @@ -package org.toop.frontend.UI; +package org.toop.app.gui; import java.awt.event.ActionEvent; import java.util.Objects; @@ -7,11 +7,12 @@ import java.util.concurrent.ExecutionException; import javax.swing.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.toop.eventbus.events.Events; -import org.toop.eventbus.GlobalEventBus; -import org.toop.eventbus.events.NetworkEvents; -import org.toop.frontend.games.LocalTicTacToe; -import org.toop.frontend.networking.NetworkingGameClientHandler; +import org.toop.framework.eventbus.events.Events; +import org.toop.framework.eventbus.GlobalEventBus; +import org.toop.framework.eventbus.events.NetworkEvents; +import org.toop.app.tictactoe.LocalTicTacToe; +import org.toop.framework.networking.NetworkingGameClientHandler; +import org.toop.app.tictactoe.gui.UIGameBoard; public class RemoteGameSelector { private static final Logger logger = LogManager.getLogger(RemoteGameSelector.class); diff --git a/src/main/java/org/toop/frontend/games/LocalTicTacToe.java b/src/main/java/org/toop/app/tictactoe/LocalTicTacToe.java similarity index 95% rename from src/main/java/org/toop/frontend/games/LocalTicTacToe.java rename to src/main/java/org/toop/app/tictactoe/LocalTicTacToe.java index 0ba203a..41d2a43 100644 --- a/src/main/java/org/toop/frontend/games/LocalTicTacToe.java +++ b/src/main/java/org/toop/app/tictactoe/LocalTicTacToe.java @@ -1,29 +1,25 @@ -package org.toop.frontend.games; +package org.toop.app.tictactoe; import java.util.concurrent.*; -import jdk.jfr.Event; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.toop.eventbus.EventPublisher; -import org.toop.eventbus.events.Events; -import org.toop.eventbus.GlobalEventBus; -import org.toop.eventbus.events.NetworkEvents; -import org.toop.frontend.UI.UIGameBoard; -import org.toop.frontend.networking.NetworkingGameClientHandler; -import org.toop.game.tictactoe.GameBase; -import org.toop.game.tictactoe.TicTacToe; +import org.toop.framework.eventbus.events.Events; +import org.toop.framework.eventbus.events.NetworkEvents; +import org.toop.app.tictactoe.gui.UIGameBoard; +import org.toop.framework.networking.NetworkingGameClientHandler; +import org.toop.app.GameBase; import org.toop.game.tictactoe.ai.MinMaxTicTacToe; import java.util.function.Supplier; import static java.lang.Thread.sleep; -import static java.lang.Thread.sleep; - /** * A representation of a local tic-tac-toe game. Calls are made to a server for information about * current game state. MOST OF THIS CODE IS TRASH, THROW IT OUT OF THE WINDOW AFTER DEMO. */ +// Todo: refactor public class LocalTicTacToe { // TODO: Implement runnable private static final Logger logger = LogManager.getLogger(LocalTicTacToe.class); diff --git a/src/main/java/org/toop/game/tictactoe/TicTacToe.java b/src/main/java/org/toop/app/tictactoe/TicTacToe.java similarity index 98% rename from src/main/java/org/toop/game/tictactoe/TicTacToe.java rename to src/main/java/org/toop/app/tictactoe/TicTacToe.java index 83d7e9b..bf7849f 100644 --- a/src/main/java/org/toop/game/tictactoe/TicTacToe.java +++ b/src/main/java/org/toop/app/tictactoe/TicTacToe.java @@ -1,12 +1,15 @@ -package org.toop.game.tictactoe; +package org.toop.app.tictactoe; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.toop.app.GameBase; +import org.toop.app.Player; import org.toop.backend.tictactoe.ParsedCommand; import org.toop.backend.tictactoe.TicTacToeServerCommand; +// Todo: refactor public class TicTacToe extends GameBase implements Runnable { protected static final Logger logger = LogManager.getLogger(TicTacToe.class); diff --git a/src/main/java/org/toop/app/tictactoe/TicTacToeAI.java b/src/main/java/org/toop/app/tictactoe/TicTacToeAI.java new file mode 100644 index 0000000..079f356 --- /dev/null +++ b/src/main/java/org/toop/app/tictactoe/TicTacToeAI.java @@ -0,0 +1,139 @@ +package org.toop.app.tictactoe; + +import org.toop.app.GameBase; + +// Todo: refactor +public class TicTacToeAI { + /** + * This method tries to find the best move by seeing if it can set a winning move, if not, it + * will do a minimax. + */ + public int findBestMove(TicTacToe game) { + int bestVal = -100; // set bestVal to something impossible + int bestMove = 10; // set bestMove to something impossible + + int winningMove = -5; + + boolean empty = true; + for (char cell : game.grid) { + if (!(cell == GameBase.EMPTY)) { + empty = false; + break; + } + } + + if (empty) { // start in a random corner + return switch ((int) (Math.random() * 4)) { + case 1 -> 2; + case 2 -> 6; + case 3 -> 8; + default -> 0; + }; + } + + // simulate all possible moves on the field + for (int i = 0; i < game.grid.length; i++) { + + if (game.validateMove(i)) { // check if the move is legal here + TicTacToe copyGame = game.copyBoard(); // make a copy of the game + GameBase.State result = copyGame.play(i); // play a move on the copy board + + int thisMoveValue; + + if (result == GameBase.State.WIN) { + return i; // just return right away if you can win on the next move + } + + for (int index = 0; index < game.grid.length; index++) { + if (game.validateMove(index)) { + TicTacToe opponentCopy = copyGame.copyBoard(); + GameBase.State opponentResult = opponentCopy.play(index); + if (opponentResult == GameBase.State.WIN) { + winningMove = index; + } + } + } + + thisMoveValue = + doMinimax(copyGame, game.movesLeft, false); // else look at other moves + if (thisMoveValue + > bestVal) { // if better move than the current best, change the move + bestVal = thisMoveValue; + bestMove = i; + } + } + } + if (winningMove > -5) { + return winningMove; + } + return bestMove; // return the best move when we've done everything + } + + /** + * This method simulates all the possible future moves in the game through a copy in search of + * the best move. + */ + public int doMinimax(TicTacToe game, int depth, boolean maximizing) { + boolean state = game.checkWin(); // check for a win (base case stuff) + + if (state) { + if (maximizing) { + // it's the maximizing players turn and someone has won. this is not good, so return + // a negative value + return -10 + depth; + } else { + // it is the turn of the AI and it has won! this is good for us, so return a + // positive value above 0 + return 10 - depth; + } + } else { + boolean empty = false; + for (char cell : + game.grid) { // else, look at draw conditions. we check per cell if it's empty + // or not + if (cell == GameBase.EMPTY) { + empty = true; // if a thing is empty, set to true + break; // break the loop + } + } + if (!empty + || depth == 0) { // if the grid is full or the depth is 0 (both meaning game is + // over) return 0 for draw + return 0; + } + } + + int bestVal; // set the value to the highest possible + if (maximizing) { // it's the maximizing players turn, the AI + bestVal = -100; + for (int i = 0; i < game.grid.length; i++) { // loop through the grid + if (game.validateMove(i)) { + TicTacToe copyGame = game.copyBoard(); + copyGame.play(i); // play the move on a copy board + int value = + doMinimax(copyGame, depth - 1, false); // keep going with the minimax + bestVal = + Math.max( + bestVal, + value); // select the best value for the maximizing player (the + // AI) + } + } + } else { // it's the minimizing players turn, the player + bestVal = 100; + for (int i = 0; i < game.grid.length; i++) { // loop through the grid + if (game.validateMove(i)) { + TicTacToe copyGame = game.copyBoard(); + copyGame.play(i); // play the move on a copy board + int value = doMinimax(copyGame, depth - 1, true); // keep miniMaxing + bestVal = + Math.min( + bestVal, + value); // select the lowest score for the minimizing player, + // they want to make it hard for us + } + } + } + return bestVal; + } +} \ No newline at end of file diff --git a/src/main/java/org/toop/frontend/UI/UIGameBoard.form b/src/main/java/org/toop/app/tictactoe/gui/UIGameBoard.form similarity index 94% rename from src/main/java/org/toop/frontend/UI/UIGameBoard.form rename to src/main/java/org/toop/app/tictactoe/gui/UIGameBoard.form index 6f76e01..192a038 100644 --- a/src/main/java/org/toop/frontend/UI/UIGameBoard.form +++ b/src/main/java/org/toop/app/tictactoe/gui/UIGameBoard.form @@ -1,5 +1,5 @@ - + diff --git a/src/main/java/org/toop/frontend/UI/UIGameBoard.java b/src/main/java/org/toop/app/tictactoe/gui/UIGameBoard.java similarity index 96% rename from src/main/java/org/toop/frontend/UI/UIGameBoard.java rename to src/main/java/org/toop/app/tictactoe/gui/UIGameBoard.java index ce36e3e..92f4ef2 100644 --- a/src/main/java/org/toop/frontend/UI/UIGameBoard.java +++ b/src/main/java/org/toop/app/tictactoe/gui/UIGameBoard.java @@ -1,12 +1,14 @@ -package org.toop.frontend.UI; +package org.toop.app.tictactoe.gui; import java.awt.*; import java.awt.event.ActionEvent; import javax.swing.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.toop.frontend.games.LocalTicTacToe; -import org.toop.game.tictactoe.GameBase; +import org.toop.app.gui.LocalGameSelector; +import org.toop.app.gui.RemoteGameSelector; +import org.toop.app.tictactoe.LocalTicTacToe; +import org.toop.app.GameBase; public class UIGameBoard { private static final int TICTACTOE_SIZE = 3; diff --git a/src/main/java/org/toop/eventbus/events/IEvent.java b/src/main/java/org/toop/eventbus/events/IEvent.java deleted file mode 100644 index 41ee649..0000000 --- a/src/main/java/org/toop/eventbus/events/IEvent.java +++ /dev/null @@ -1,3 +0,0 @@ -package org.toop.eventbus.events; - -public interface IEvent {} diff --git a/src/main/java/org/toop/eventbus/events/ServerEvents.java b/src/main/java/org/toop/eventbus/events/ServerEvents.java deleted file mode 100644 index ccf02c1..0000000 --- a/src/main/java/org/toop/eventbus/events/ServerEvents.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.toop.eventbus.events; - -public class ServerEvents { -} diff --git a/src/main/java/org/toop/framework/Logging.java b/src/main/java/org/toop/framework/Logging.java new file mode 100644 index 0000000..abd13cc --- /dev/null +++ b/src/main/java/org/toop/framework/Logging.java @@ -0,0 +1,202 @@ +package org.toop.framework; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.LoggerConfig; + +/** + * Utility class for configuring logging levels dynamically at runtime using Log4j 2. + * + *

Provides methods to enable or disable logs globally or per class, with support for specifying + * log levels either via {@link Level} enums or string names. + */ +// Todo: refactor +public final class Logging { + + /** Disables all logging globally by setting the root logger level to {@link Level#OFF}. */ + public static void disableAllLogs() { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig rootLoggerConfig = config.getRootLogger(); + rootLoggerConfig.setLevel(Level.OFF); + ctx.updateLoggers(); + } + + /** Enables all logging globally by setting the root logger level to {@link Level#ALL}. */ + public static void enableAllLogs() { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig rootLoggerConfig = config.getRootLogger(); + rootLoggerConfig.setLevel(Level.ALL); + ctx.updateLoggers(); + } + + /** + * Enables global logging at a specific level by setting the root logger. + * + * @param level the logging level to enable for all logs + */ + public static void enableAllLogs(Level level) { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig rootLoggerConfig = config.getRootLogger(); + rootLoggerConfig.setLevel(level); + ctx.updateLoggers(); + } + + /** + * Verifies whether the provided string corresponds to a valid class name. + * + * @param className fully-qualified class name to check + * @return true if the class exists, false otherwise + */ + private static boolean verifyStringIsActualClass(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + /** + * Internal helper to disable logs for a specific class by name. + * + * @param className fully-qualified class name + */ + private static void disableLogsForClassInternal(String className) { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + config.removeLogger(className); + LoggerConfig specificConfig = new LoggerConfig(className, Level.OFF, false); + config.addLogger(className, specificConfig); + ctx.updateLoggers(); + } + + /** + * Disables logs for a specific class. + * + * @param class_ the class for which logs should be disabled + * @param type of the class + */ + public static void disableLogsForClass(Class class_) { + disableLogsForClassInternal(class_.getName()); + } + + /** + * Disables logs for a class specified by fully-qualified name, if the class exists. + * + * @param className fully-qualified class name + */ + public static void disableLogsForClass(String className) { + if (verifyStringIsActualClass(className)) { + disableLogsForClassInternal(className); + } + } + + /** + * Internal helper to enable logs for a specific class at a specific level. + * + * @param className fully-qualified class name + * @param level logging level to set + */ + private static void enableLogsForClassInternal(String className, Level level) { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig loggerConfig = config.getLoggers().get(className); + if (loggerConfig == null) { + loggerConfig = new LoggerConfig(className, level, false); + config.addLogger(className, loggerConfig); + } else { + loggerConfig.setLevel(level); + } + ctx.updateLoggers(); + } + + /** + * Enables logging for a class at a specific level. + * + * @param class_ class to configure + * @param levelToLog the logging level to set + * @param type of the class + */ + public static void enableLogsForClass(Class class_, Level levelToLog) { + enableLogsForClassInternal(class_.getName(), levelToLog); + } + + /** + * Enables logging for a class specified by name at a specific level, if the class exists. + * + * @param className fully-qualified class name + * @param levelToLog the logging level to set + */ + public static void enableLogsForClass(String className, Level levelToLog) { + if (verifyStringIsActualClass(className)) { + enableLogsForClassInternal(className, levelToLog); + } + } + + /** + * Enables logging for a class specified by name at a specific level using a string. + * + * @param className fully-qualified class name + * @param levelToLog name of the logging level (e.g., "DEBUG", "INFO") + */ + public static void enableLogsForClass(String className, String levelToLog) { + Level level = Level.valueOf(levelToLog.trim().toUpperCase()); + if (level != null && verifyStringIsActualClass(className)) { + enableLogsForClassInternal(className, level); + } + } + + /** Convenience methods for enabling logs at specific levels for classes. */ + public static void enableAllLogsForClass(Class class_) { + enableLogsForClass(class_, Level.ALL); + } + + public static void enableAllLogsForClass(String className) { + enableLogsForClass(className, Level.ALL); + } + + public static void enableDebugLogsForClass(Class class_) { + enableLogsForClass(class_, Level.DEBUG); + } + + public static void enableDebugLogsForClass(String className) { + enableLogsForClass(className, Level.DEBUG); + } + + public static void enableErrorLogsForClass(Class class_) { + enableLogsForClass(class_, Level.ERROR); + } + + public static void enableErrorLogsForClass(String className) { + enableLogsForClass(className, Level.ERROR); + } + + public static void enableFatalLogsForClass(Class class_) { + enableLogsForClass(class_, Level.FATAL); + } + + public static void enableFatalLogsForClass(String className) { + enableLogsForClass(className, Level.FATAL); + } + + public static void enableInfoLogsForClass(Class class_) { + enableLogsForClass(class_, Level.INFO); + } + + public static void enableInfoLogsForClass(String className) { + enableLogsForClass(className, Level.INFO); + } + + public static void enableTraceLogsForClass(Class class_) { + enableLogsForClass(class_, Level.TRACE); + } + + public static void enableTraceLogsForClass(String className) { + enableLogsForClass(className, Level.TRACE); + } +} \ No newline at end of file diff --git a/src/main/java/org/toop/eventbus/EventFlow.java b/src/main/java/org/toop/framework/eventbus/EventFlow.java similarity index 98% rename from src/main/java/org/toop/eventbus/EventFlow.java rename to src/main/java/org/toop/framework/eventbus/EventFlow.java index f5c4f14..92e2372 100644 --- a/src/main/java/org/toop/eventbus/EventFlow.java +++ b/src/main/java/org/toop/framework/eventbus/EventFlow.java @@ -1,7 +1,7 @@ -package org.toop.eventbus; +package org.toop.framework.eventbus; -import org.toop.eventbus.events.EventWithUuid; -import org.toop.eventbus.events.IEvent; +import org.toop.framework.eventbus.events.EventWithUuid; +import org.toop.framework.eventbus.events.IEvent; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; diff --git a/src/main/java/org/toop/eventbus/GlobalEventBus.java b/src/main/java/org/toop/framework/eventbus/GlobalEventBus.java similarity index 98% rename from src/main/java/org/toop/eventbus/GlobalEventBus.java rename to src/main/java/org/toop/framework/eventbus/GlobalEventBus.java index 98897ed..acc15a9 100644 --- a/src/main/java/org/toop/eventbus/GlobalEventBus.java +++ b/src/main/java/org/toop/framework/eventbus/GlobalEventBus.java @@ -1,7 +1,7 @@ -package org.toop.eventbus; +package org.toop.framework.eventbus; -import org.toop.eventbus.events.EventWithUuid; -import org.toop.eventbus.events.IEvent; +import org.toop.framework.eventbus.events.EventWithUuid; +import org.toop.framework.eventbus.events.IEvent; import java.util.Map; import java.util.concurrent.*; diff --git a/src/main/java/org/toop/eventbus/events/EventWithUuid.java b/src/main/java/org/toop/framework/eventbus/events/EventWithUuid.java similarity index 74% rename from src/main/java/org/toop/eventbus/events/EventWithUuid.java rename to src/main/java/org/toop/framework/eventbus/events/EventWithUuid.java index 236c1ce..3ec2ea8 100644 --- a/src/main/java/org/toop/eventbus/events/EventWithUuid.java +++ b/src/main/java/org/toop/framework/eventbus/events/EventWithUuid.java @@ -1,4 +1,4 @@ -package org.toop.eventbus.events; +package org.toop.framework.eventbus.events; import java.util.Map; diff --git a/src/main/java/org/toop/eventbus/events/Events.java b/src/main/java/org/toop/framework/eventbus/events/Events.java similarity index 98% rename from src/main/java/org/toop/eventbus/events/Events.java rename to src/main/java/org/toop/framework/eventbus/events/Events.java index 3bbba53..6ba3327 100644 --- a/src/main/java/org/toop/eventbus/events/Events.java +++ b/src/main/java/org/toop/framework/eventbus/events/Events.java @@ -1,6 +1,4 @@ -package org.toop.eventbus.events; - -import org.apache.logging.log4j.core.jmx.Server; +package org.toop.framework.eventbus.events; import java.lang.reflect.Constructor; import java.util.Arrays; diff --git a/src/main/java/org/toop/framework/eventbus/events/IEvent.java b/src/main/java/org/toop/framework/eventbus/events/IEvent.java new file mode 100644 index 0000000..1867942 --- /dev/null +++ b/src/main/java/org/toop/framework/eventbus/events/IEvent.java @@ -0,0 +1,3 @@ +package org.toop.framework.eventbus.events; + +public interface IEvent {} diff --git a/src/main/java/org/toop/eventbus/events/NetworkEvents.java b/src/main/java/org/toop/framework/eventbus/events/NetworkEvents.java similarity index 98% rename from src/main/java/org/toop/eventbus/events/NetworkEvents.java rename to src/main/java/org/toop/framework/eventbus/events/NetworkEvents.java index 1a3dd56..7b9dbbd 100644 --- a/src/main/java/org/toop/eventbus/events/NetworkEvents.java +++ b/src/main/java/org/toop/framework/eventbus/events/NetworkEvents.java @@ -1,7 +1,7 @@ -package org.toop.eventbus.events; +package org.toop.framework.eventbus.events; import org.toop.backend.tictactoe.TicTacToeServer; -import org.toop.frontend.networking.NetworkingGameClientHandler; +import org.toop.framework.networking.NetworkingGameClientHandler; import java.lang.reflect.RecordComponent; import java.util.*; diff --git a/src/main/java/org/toop/framework/eventbus/events/ServerEvents.java b/src/main/java/org/toop/framework/eventbus/events/ServerEvents.java new file mode 100644 index 0000000..d7c0ef8 --- /dev/null +++ b/src/main/java/org/toop/framework/eventbus/events/ServerEvents.java @@ -0,0 +1,4 @@ +package org.toop.framework.eventbus.events; + +public class ServerEvents { +} diff --git a/src/main/java/org/toop/frontend/networking/NetworkingClient.java b/src/main/java/org/toop/framework/networking/NetworkingClient.java similarity index 99% rename from src/main/java/org/toop/frontend/networking/NetworkingClient.java rename to src/main/java/org/toop/framework/networking/NetworkingClient.java index 4982053..91143ec 100644 --- a/src/main/java/org/toop/frontend/networking/NetworkingClient.java +++ b/src/main/java/org/toop/framework/networking/NetworkingClient.java @@ -1,4 +1,4 @@ -package org.toop.frontend.networking; +package org.toop.framework.networking; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; diff --git a/src/main/java/org/toop/frontend/networking/NetworkingClientManager.java b/src/main/java/org/toop/framework/networking/NetworkingClientManager.java similarity index 97% rename from src/main/java/org/toop/frontend/networking/NetworkingClientManager.java rename to src/main/java/org/toop/framework/networking/NetworkingClientManager.java index 81c47e7..d11a9ff 100644 --- a/src/main/java/org/toop/frontend/networking/NetworkingClientManager.java +++ b/src/main/java/org/toop/framework/networking/NetworkingClientManager.java @@ -1,4 +1,4 @@ -package org.toop.frontend.networking; +package org.toop.framework.networking; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -7,8 +7,7 @@ import java.util.function.Supplier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.toop.eventbus.EventPublisher; -import org.toop.eventbus.GlobalEventBus; -import org.toop.eventbus.events.NetworkEvents; +import org.toop.framework.eventbus.events.NetworkEvents; public class NetworkingClientManager { diff --git a/src/main/java/org/toop/frontend/networking/NetworkingGameClientHandler.java b/src/main/java/org/toop/framework/networking/NetworkingGameClientHandler.java similarity index 95% rename from src/main/java/org/toop/frontend/networking/NetworkingGameClientHandler.java rename to src/main/java/org/toop/framework/networking/NetworkingGameClientHandler.java index 8decbd4..0b7ca49 100644 --- a/src/main/java/org/toop/frontend/networking/NetworkingGameClientHandler.java +++ b/src/main/java/org/toop/framework/networking/NetworkingGameClientHandler.java @@ -1,4 +1,4 @@ -package org.toop.frontend.networking; +package org.toop.framework.networking; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; diff --git a/src/main/java/org/toop/frontend/networking/handlers/NetworkingTicTacToeClientHandler.java b/src/main/java/org/toop/framework/networking/handlers/NetworkingTicTacToeClientHandler.java similarity index 100% rename from src/main/java/org/toop/frontend/networking/handlers/NetworkingTicTacToeClientHandler.java rename to src/main/java/org/toop/framework/networking/handlers/NetworkingTicTacToeClientHandler.java diff --git a/src/main/java/org/toop/frontend/UI/Services.form b/src/main/java/org/toop/frontend/UI/Services.form deleted file mode 100644 index c04ea22..0000000 --- a/src/main/java/org/toop/frontend/UI/Services.form +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/src/main/java/org/toop/frontend/UI/Services.java b/src/main/java/org/toop/frontend/UI/Services.java deleted file mode 100644 index 988ba0e..0000000 --- a/src/main/java/org/toop/frontend/UI/Services.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.toop.frontend.UI; - -import javax.swing.*; - -public class Services {} diff --git a/src/main/java/org/toop/game/tictactoe/GameBase.java b/src/main/java/org/toop/game/tictactoe/GameBase.java deleted file mode 100644 index ff0aa91..0000000 --- a/src/main/java/org/toop/game/tictactoe/GameBase.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.toop.game.tictactoe; - -public abstract class GameBase { - public enum State { - INVALID, - - NORMAL, - DRAW, - WIN, - } - - public static char EMPTY = '-'; - - protected int size; - public char[] grid; - - protected Player[] players; - public int currentPlayer; - - public GameBase(int size, Player player1, Player player2) { - this.size = size; - grid = new char[size * size]; - - for (int i = 0; i < grid.length; i++) { - grid[i] = EMPTY; - } - - players = new Player[2]; - players[0] = player1; - players[1] = player2; - - currentPlayer = 0; - } - - public boolean isInside(int index) { - return index >= 0 && index < size * size; - } - - public int getSize() { - return size; - } - - public char[] getGrid() { - return grid; - } - - public Player[] getPlayers() { - return players; - } - - public Player getCurrentPlayer() { - return players[currentPlayer]; - } - - public abstract State play(int index); -} diff --git a/src/main/java/org/toop/game/tictactoe/Player.java b/src/main/java/org/toop/game/tictactoe/Player.java deleted file mode 100644 index b3ef400..0000000 --- a/src/main/java/org/toop/game/tictactoe/Player.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.toop.game.tictactoe; - -public class Player { - - String name; - char symbol; - - Player(String name, char symbol) { - this.name = name; - this.symbol = symbol; - } - - public String getName() { - return this.name; - } - - public char getSymbol() { - return this.symbol; - } -} diff --git a/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java b/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java deleted file mode 100644 index dd97b96..0000000 --- a/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.toop.game.tictactoe.ai; - -import org.toop.game.tictactoe.GameBase; -import org.toop.game.tictactoe.TicTacToe; - -public class MinMaxTicTacToe { - - /** - * This method tries to find the best move by seeing if it can set a winning move, if not, it - * will do a minimax. - */ - public int findBestMove(TicTacToe game) { - int bestVal = -100; // set bestVal to something impossible - int bestMove = 10; // set bestMove to something impossible - - int winningMove = -5; - - boolean empty = true; - for (char cell : game.grid) { - if (!(cell == GameBase.EMPTY)) { - empty = false; - break; - } - } - - if (empty) { // start in a random corner - return switch ((int) (Math.random() * 4)) { - case 1 -> 2; - case 2 -> 6; - case 3 -> 8; - default -> 0; - }; - } - - // simulate all possible moves on the field - for (int i = 0; i < game.grid.length; i++) { - - if (game.validateMove(i)) { // check if the move is legal here - TicTacToe copyGame = game.copyBoard(); // make a copy of the game - GameBase.State result = copyGame.play(i); // play a move on the copy board - - int thisMoveValue; - - if (result == GameBase.State.WIN) { - return i; // just return right away if you can win on the next move - } - - for (int index = 0; index < game.grid.length; index++) { - if (game.validateMove(index)) { - TicTacToe opponentCopy = copyGame.copyBoard(); - GameBase.State opponentResult = opponentCopy.play(index); - if (opponentResult == GameBase.State.WIN) { - winningMove = index; - } - } - } - - thisMoveValue = - doMinimax(copyGame, game.movesLeft, false); // else look at other moves - if (thisMoveValue - > bestVal) { // if better move than the current best, change the move - bestVal = thisMoveValue; - bestMove = i; - } - } - } - if (winningMove > -5) { - return winningMove; - } - return bestMove; // return the best move when we've done everything - } - - /** - * This method simulates all the possible future moves in the game through a copy in search of - * the best move. - */ - public int doMinimax(TicTacToe game, int depth, boolean maximizing) { - boolean state = game.checkWin(); // check for a win (base case stuff) - - if (state) { - if (maximizing) { - // it's the maximizing players turn and someone has won. this is not good, so return - // a negative value - return -10 + depth; - } else { - // it is the turn of the AI and it has won! this is good for us, so return a - // positive value above 0 - return 10 - depth; - } - } else { - boolean empty = false; - for (char cell : - game.grid) { // else, look at draw conditions. we check per cell if it's empty - // or not - if (cell == GameBase.EMPTY) { - empty = true; // if a thing is empty, set to true - break; // break the loop - } - } - if (!empty - || depth == 0) { // if the grid is full or the depth is 0 (both meaning game is - // over) return 0 for draw - return 0; - } - } - - int bestVal; // set the value to the highest possible - if (maximizing) { // it's the maximizing players turn, the AI - bestVal = -100; - for (int i = 0; i < game.grid.length; i++) { // loop through the grid - if (game.validateMove(i)) { - TicTacToe copyGame = game.copyBoard(); - copyGame.play(i); // play the move on a copy board - int value = - doMinimax(copyGame, depth - 1, false); // keep going with the minimax - bestVal = - Math.max( - bestVal, - value); // select the best value for the maximizing player (the - // AI) - } - } - } else { // it's the minimizing players turn, the player - bestVal = 100; - for (int i = 0; i < game.grid.length; i++) { // loop through the grid - if (game.validateMove(i)) { - TicTacToe copyGame = game.copyBoard(); - copyGame.play(i); // play the move on a copy board - int value = doMinimax(copyGame, depth - 1, true); // keep miniMaxing - bestVal = - Math.min( - bestVal, - value); // select the lowest score for the minimizing player, - // they want to make it hard for us - } - } - } - return bestVal; - } -} diff --git a/src/test/java/org/toop/LoggingTest.java b/src/test/java/org/toop/LoggingTest.java index b979802..af2f733 100644 --- a/src/test/java/org/toop/LoggingTest.java +++ b/src/test/java/org/toop/LoggingTest.java @@ -9,6 +9,7 @@ import org.apache.logging.log4j.core.config.LoggerConfig; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.toop.framework.Logging; public class LoggingTest { diff --git a/src/test/java/org/toop/eventbus/EventPublisherSpeedTest.java b/src/test/java/org/toop/eventbus/EventPublisherSpeedTest.java index 4f2d65d..4653036 100644 --- a/src/test/java/org/toop/eventbus/EventPublisherSpeedTest.java +++ b/src/test/java/org/toop/eventbus/EventPublisherSpeedTest.java @@ -1,7 +1,8 @@ package org.toop.eventbus; import org.junit.jupiter.api.Test; -import org.toop.eventbus.events.EventWithUuid; +import org.toop.framework.eventbus.GlobalEventBus; +import org.toop.framework.eventbus.events.EventWithUuid; import java.util.concurrent.atomic.AtomicInteger; diff --git a/src/test/java/org/toop/eventbus/EventPublisherStressTest.java b/src/test/java/org/toop/eventbus/EventPublisherStressTest.java index 513fc66..1bbca31 100644 --- a/src/test/java/org/toop/eventbus/EventPublisherStressTest.java +++ b/src/test/java/org/toop/eventbus/EventPublisherStressTest.java @@ -2,12 +2,10 @@ package org.toop.eventbus; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -import org.toop.eventbus.events.EventWithUuid; +import org.toop.framework.eventbus.events.EventWithUuid; import java.math.BigInteger; -import java.util.UUID; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAdder; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/org/toop/eventbus/EventPublisherTest.java b/src/test/java/org/toop/eventbus/EventPublisherTest.java index 0fd37b1..9602009 100644 --- a/src/test/java/org/toop/eventbus/EventPublisherTest.java +++ b/src/test/java/org/toop/eventbus/EventPublisherTest.java @@ -1,7 +1,7 @@ package org.toop.eventbus; import org.junit.jupiter.api.Test; -import org.toop.eventbus.events.EventWithUuid; +import org.toop.framework.eventbus.events.EventWithUuid; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/src/test/java/org/toop/game/tictactoe/GameBaseTest.java b/src/test/java/org/toop/game/tictactoe/GameBaseTest.java index dd56230..dd618c4 100644 --- a/src/test/java/org/toop/game/tictactoe/GameBaseTest.java +++ b/src/test/java/org/toop/game/tictactoe/GameBaseTest.java @@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.toop.app.GameBase; +import org.toop.app.Player; class GameBaseTest { diff --git a/src/test/java/org/toop/game/tictactoe/PlayerTest.java b/src/test/java/org/toop/game/tictactoe/PlayerTest.java index 48f6930..76b5743 100644 --- a/src/test/java/org/toop/game/tictactoe/PlayerTest.java +++ b/src/test/java/org/toop/game/tictactoe/PlayerTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.toop.app.Player; class PlayerTest { diff --git a/src/test/java/org/toop/game/tictactoe/ai/MinMaxTicTacToeTest.java b/src/test/java/org/toop/game/tictactoe/ai/MinMaxTicTacToeTest.java index 9c2e0be..fad8aef 100644 --- a/src/test/java/org/toop/game/tictactoe/ai/MinMaxTicTacToeTest.java +++ b/src/test/java/org/toop/game/tictactoe/ai/MinMaxTicTacToeTest.java @@ -5,8 +5,8 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.toop.game.tictactoe.GameBase; -import org.toop.game.tictactoe.TicTacToe; +import org.toop.app.GameBase; +import org.toop.app.tictactoe.TicTacToe; /** Unit tests for MinMaxTicTacToe AI. */ public class MinMaxTicTacToeTest {