mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
refactored the file structure. nothing works :)
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>org.toop</groupId>
|
<groupId>org.toop</groupId>
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
<maven.compiler.source>24</maven.compiler.source>
|
<maven.compiler.source>24</maven.compiler.source>
|
||||||
<maven.compiler.target>24</maven.compiler.target>
|
<maven.compiler.target>24</maven.compiler.target>
|
||||||
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
<main-class>org.toop.Main</main-class>
|
<main-class>org.toop.Main</main-class>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -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.
|
|
||||||
*
|
|
||||||
* <p>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 <T> type of the class
|
|
||||||
*/
|
|
||||||
public static <T> void disableLogsForClass(Class<T> 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 <T> type of the class
|
|
||||||
*/
|
|
||||||
public static <T> void enableLogsForClass(Class<T> 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 <T> void enableAllLogsForClass(Class<T> class_) {
|
|
||||||
enableLogsForClass(class_, Level.ALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableAllLogsForClass(String className) {
|
|
||||||
enableLogsForClass(className, Level.ALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void enableDebugLogsForClass(Class<T> class_) {
|
|
||||||
enableLogsForClass(class_, Level.DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableDebugLogsForClass(String className) {
|
|
||||||
enableLogsForClass(className, Level.DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void enableErrorLogsForClass(Class<T> class_) {
|
|
||||||
enableLogsForClass(class_, Level.ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableErrorLogsForClass(String className) {
|
|
||||||
enableLogsForClass(className, Level.ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void enableFatalLogsForClass(Class<T> class_) {
|
|
||||||
enableLogsForClass(class_, Level.FATAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableFatalLogsForClass(String className) {
|
|
||||||
enableLogsForClass(className, Level.FATAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void enableInfoLogsForClass(Class<T> class_) {
|
|
||||||
enableLogsForClass(class_, Level.INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableInfoLogsForClass(String className) {
|
|
||||||
enableLogsForClass(className, Level.INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void enableTraceLogsForClass(Class<T> class_) {
|
|
||||||
enableLogsForClass(class_, Level.TRACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableTraceLogsForClass(String className) {
|
|
||||||
enableLogsForClass(className, Level.TRACE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +1,6 @@
|
|||||||
package org.toop;
|
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 {
|
public class Main {
|
||||||
private static final Logger logger = LogManager.getLogger(Main.class);
|
public static void main(String[] args) {
|
||||||
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<String> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
57
src/main/java/org/toop/app/GameBase.java
Normal file
57
src/main/java/org/toop/app/GameBase.java
Normal file
@@ -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);
|
||||||
|
}
|
||||||
20
src/main/java/org/toop/app/Player.java
Normal file
20
src/main/java/org/toop/app/Player.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.frontend.UI;
|
package org.toop.app.gui;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.LocalGameSelector">
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.gui.LocalGameSelector">
|
||||||
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package org.toop.frontend.UI;
|
package org.toop.app.gui;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
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 {
|
public class LocalGameSelector extends JFrame {
|
||||||
private static final Logger logger = LogManager.getLogger(LocalGameSelector.class);
|
private static final Logger logger = LogManager.getLogger(LocalGameSelector.class);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.LocalServerSelector">
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.gui.LocalServerSelector">
|
||||||
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.frontend.UI;
|
package org.toop.app.gui;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.RemoteGameSelector">
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.gui.RemoteGameSelector">
|
||||||
<grid id="27dc6" binding="mainMenu" layout-manager="GridLayoutManager" row-count="10" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="mainMenu" layout-manager="GridLayoutManager" row-count="10" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="10" left="10" bottom="10" right="10"/>
|
<margin top="10" left="10" bottom="10" right="10"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.frontend.UI;
|
package org.toop.app.gui;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -7,11 +7,12 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.toop.eventbus.events.Events;
|
import org.toop.framework.eventbus.events.Events;
|
||||||
import org.toop.eventbus.GlobalEventBus;
|
import org.toop.framework.eventbus.GlobalEventBus;
|
||||||
import org.toop.eventbus.events.NetworkEvents;
|
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||||
import org.toop.frontend.games.LocalTicTacToe;
|
import org.toop.app.tictactoe.LocalTicTacToe;
|
||||||
import org.toop.frontend.networking.NetworkingGameClientHandler;
|
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||||
|
import org.toop.app.tictactoe.gui.UIGameBoard;
|
||||||
|
|
||||||
public class RemoteGameSelector {
|
public class RemoteGameSelector {
|
||||||
private static final Logger logger = LogManager.getLogger(RemoteGameSelector.class);
|
private static final Logger logger = LogManager.getLogger(RemoteGameSelector.class);
|
||||||
@@ -1,29 +1,25 @@
|
|||||||
package org.toop.frontend.games;
|
package org.toop.app.tictactoe;
|
||||||
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
import jdk.jfr.Event;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.toop.eventbus.EventPublisher;
|
import org.toop.eventbus.EventPublisher;
|
||||||
import org.toop.eventbus.events.Events;
|
import org.toop.framework.eventbus.events.Events;
|
||||||
import org.toop.eventbus.GlobalEventBus;
|
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||||
import org.toop.eventbus.events.NetworkEvents;
|
import org.toop.app.tictactoe.gui.UIGameBoard;
|
||||||
import org.toop.frontend.UI.UIGameBoard;
|
import org.toop.framework.networking.NetworkingGameClientHandler;
|
||||||
import org.toop.frontend.networking.NetworkingGameClientHandler;
|
import org.toop.app.GameBase;
|
||||||
import org.toop.game.tictactoe.GameBase;
|
|
||||||
import org.toop.game.tictactoe.TicTacToe;
|
|
||||||
import org.toop.game.tictactoe.ai.MinMaxTicTacToe;
|
import org.toop.game.tictactoe.ai.MinMaxTicTacToe;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static java.lang.Thread.sleep;
|
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
|
* 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.
|
* 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
|
public class LocalTicTacToe { // TODO: Implement runnable
|
||||||
private static final Logger logger = LogManager.getLogger(LocalTicTacToe.class);
|
private static final Logger logger = LogManager.getLogger(LocalTicTacToe.class);
|
||||||
|
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
package org.toop.game.tictactoe;
|
package org.toop.app.tictactoe;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
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.ParsedCommand;
|
||||||
import org.toop.backend.tictactoe.TicTacToeServerCommand;
|
import org.toop.backend.tictactoe.TicTacToeServerCommand;
|
||||||
|
|
||||||
|
// Todo: refactor
|
||||||
public class TicTacToe extends GameBase implements Runnable {
|
public class TicTacToe extends GameBase implements Runnable {
|
||||||
|
|
||||||
protected static final Logger logger = LogManager.getLogger(TicTacToe.class);
|
protected static final Logger logger = LogManager.getLogger(TicTacToe.class);
|
||||||
139
src/main/java/org/toop/app/tictactoe/TicTacToeAI.java
Normal file
139
src/main/java/org/toop/app/tictactoe/TicTacToeAI.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.UIGameBoard">
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.app.tictactoe.gui.UIGameBoard">
|
||||||
<grid id="27dc6" binding="tttPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="tttPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="10" left="10" bottom="10" right="10"/>
|
<margin top="10" left="10" bottom="10" right="10"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
package org.toop.frontend.UI;
|
package org.toop.app.tictactoe.gui;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.toop.frontend.games.LocalTicTacToe;
|
import org.toop.app.gui.LocalGameSelector;
|
||||||
import org.toop.game.tictactoe.GameBase;
|
import org.toop.app.gui.RemoteGameSelector;
|
||||||
|
import org.toop.app.tictactoe.LocalTicTacToe;
|
||||||
|
import org.toop.app.GameBase;
|
||||||
|
|
||||||
public class UIGameBoard {
|
public class UIGameBoard {
|
||||||
private static final int TICTACTOE_SIZE = 3;
|
private static final int TICTACTOE_SIZE = 3;
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package org.toop.eventbus.events;
|
|
||||||
|
|
||||||
public interface IEvent {}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
package org.toop.eventbus.events;
|
|
||||||
|
|
||||||
public class ServerEvents {
|
|
||||||
}
|
|
||||||
202
src/main/java/org/toop/framework/Logging.java
Normal file
202
src/main/java/org/toop/framework/Logging.java
Normal file
@@ -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.
|
||||||
|
*
|
||||||
|
* <p>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 <T> type of the class
|
||||||
|
*/
|
||||||
|
public static <T> void disableLogsForClass(Class<T> 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 <T> type of the class
|
||||||
|
*/
|
||||||
|
public static <T> void enableLogsForClass(Class<T> 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 <T> void enableAllLogsForClass(Class<T> class_) {
|
||||||
|
enableLogsForClass(class_, Level.ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableAllLogsForClass(String className) {
|
||||||
|
enableLogsForClass(className, Level.ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void enableDebugLogsForClass(Class<T> class_) {
|
||||||
|
enableLogsForClass(class_, Level.DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableDebugLogsForClass(String className) {
|
||||||
|
enableLogsForClass(className, Level.DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void enableErrorLogsForClass(Class<T> class_) {
|
||||||
|
enableLogsForClass(class_, Level.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableErrorLogsForClass(String className) {
|
||||||
|
enableLogsForClass(className, Level.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void enableFatalLogsForClass(Class<T> class_) {
|
||||||
|
enableLogsForClass(class_, Level.FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableFatalLogsForClass(String className) {
|
||||||
|
enableLogsForClass(className, Level.FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void enableInfoLogsForClass(Class<T> class_) {
|
||||||
|
enableLogsForClass(class_, Level.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableInfoLogsForClass(String className) {
|
||||||
|
enableLogsForClass(className, Level.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void enableTraceLogsForClass(Class<T> class_) {
|
||||||
|
enableLogsForClass(class_, Level.TRACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableTraceLogsForClass(String className) {
|
||||||
|
enableLogsForClass(className, Level.TRACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.toop.eventbus;
|
package org.toop.framework.eventbus;
|
||||||
|
|
||||||
import org.toop.eventbus.events.EventWithUuid;
|
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||||
import org.toop.eventbus.events.IEvent;
|
import org.toop.framework.eventbus.events.IEvent;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.toop.eventbus;
|
package org.toop.framework.eventbus;
|
||||||
|
|
||||||
import org.toop.eventbus.events.EventWithUuid;
|
import org.toop.framework.eventbus.events.EventWithUuid;
|
||||||
import org.toop.eventbus.events.IEvent;
|
import org.toop.framework.eventbus.events.IEvent;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.eventbus.events;
|
package org.toop.framework.eventbus.events;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
package org.toop.eventbus.events;
|
package org.toop.framework.eventbus.events;
|
||||||
|
|
||||||
import org.apache.logging.log4j.core.jmx.Server;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package org.toop.framework.eventbus.events;
|
||||||
|
|
||||||
|
public interface IEvent {}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.toop.eventbus.events;
|
package org.toop.framework.eventbus.events;
|
||||||
|
|
||||||
import org.toop.backend.tictactoe.TicTacToeServer;
|
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.lang.reflect.RecordComponent;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package org.toop.framework.eventbus.events;
|
||||||
|
|
||||||
|
public class ServerEvents {
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.frontend.networking;
|
package org.toop.framework.networking;
|
||||||
|
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.*;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.frontend.networking;
|
package org.toop.framework.networking;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.toop.eventbus.EventPublisher;
|
import org.toop.eventbus.EventPublisher;
|
||||||
import org.toop.eventbus.GlobalEventBus;
|
import org.toop.framework.eventbus.events.NetworkEvents;
|
||||||
import org.toop.eventbus.events.NetworkEvents;
|
|
||||||
|
|
||||||
public class NetworkingClientManager {
|
public class NetworkingClientManager {
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.frontend.networking;
|
package org.toop.framework.networking;
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.toop.frontend.UI.Services">
|
|
||||||
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<xy x="20" y="20" width="500" height="400"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children/>
|
|
||||||
</grid>
|
|
||||||
</form>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package org.toop.frontend.UI;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
public class Services {}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,6 +9,7 @@ import org.apache.logging.log4j.core.config.LoggerConfig;
|
|||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.toop.framework.Logging;
|
||||||
|
|
||||||
public class LoggingTest {
|
public class LoggingTest {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package org.toop.eventbus;
|
package org.toop.eventbus;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
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;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ package org.toop.eventbus;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Tag;
|
import org.junit.jupiter.api.Tag;
|
||||||
import org.junit.jupiter.api.Test;
|
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.math.BigInteger;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.toop.eventbus;
|
package org.toop.eventbus;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
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.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.toop.app.GameBase;
|
||||||
|
import org.toop.app.Player;
|
||||||
|
|
||||||
class GameBaseTest {
|
class GameBaseTest {
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.toop.app.Player;
|
||||||
|
|
||||||
class PlayerTest {
|
class PlayerTest {
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.toop.game.tictactoe.GameBase;
|
import org.toop.app.GameBase;
|
||||||
import org.toop.game.tictactoe.TicTacToe;
|
import org.toop.app.tictactoe.TicTacToe;
|
||||||
|
|
||||||
/** Unit tests for MinMaxTicTacToe AI. */
|
/** Unit tests for MinMaxTicTacToe AI. */
|
||||||
public class MinMaxTicTacToeTest {
|
public class MinMaxTicTacToeTest {
|
||||||
|
|||||||
Reference in New Issue
Block a user