diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..16a322c --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,21 @@ +name: Java CI with Maven + +on: + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SpielController.drawio b/SpielController.drawio index b8cac88..6b16fed 100644 --- a/SpielController.drawio +++ b/SpielController.drawio @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/intellij-java-google-style.xml b/intellij-java-google-style.xml new file mode 100644 index 0000000..6b8b9ef --- /dev/null +++ b/intellij-java-google-style.xml @@ -0,0 +1,598 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .*:.*Style + + http://schemas.android.com/apk/res/android + + + BY_NAME + +
+
+ + + + .*:layout_width + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_height + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_weight + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_margin + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginTop + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginBottom + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginStart + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginEnd + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginLeft + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_marginRight + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:layout_.* + + http://schemas.android.com/apk/res/android + + + BY_NAME + +
+
+ + + + .*:padding + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingTop + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingBottom + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingStart + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingEnd + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingLeft + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:paddingRight + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .* + http://schemas.android.com/apk/res/android + + + BY_NAME + +
+
+ + + + .* + http://schemas.android.com/apk/res-auto + + + BY_NAME + +
+
+ + + + .* + http://schemas.android.com/tools + + + BY_NAME + +
+
+ + + + .* + .* + + + BY_NAME + +
+
+
+ + +
+ + + + + + + +
diff --git a/lib/pn532/pn532-sdk/1.0.2/pn532-sdk-1.0.2.pom b/lib/pn532/pn532-sdk/1.0.2/pn532-sdk-1.0.2.pom index b37e64a..0390562 100644 --- a/lib/pn532/pn532-sdk/1.0.2/pn532-sdk-1.0.2.pom +++ b/lib/pn532/pn532-sdk/1.0.2/pn532-sdk-1.0.2.pom @@ -1,9 +1,11 @@ - - 4.0.0 - pn532 + pn532-sdk - 1.0.2 POM was created from install:install-file + pn532 + 4.0.0 + 1.0.2 diff --git a/lib/pn532/pn532-sdk/maven-metadata-local.xml b/lib/pn532/pn532-sdk/maven-metadata-local.xml index b178090..0faba88 100644 --- a/lib/pn532/pn532-sdk/maven-metadata-local.xml +++ b/lib/pn532/pn532-sdk/maven-metadata-local.xml @@ -1,12 +1,12 @@ - pn532 pn532-sdk + pn532 + 20231116111447 1.0.2 1.0.2 - 20231116111447 diff --git a/pom.xml b/pom.xml index f290ae7..32b39bd 100644 --- a/pom.xml +++ b/pom.xml @@ -1,165 +1,167 @@ - - 4.0.0 + + schafkopf-backend-java - org.example - schafkopf-backend-java - 1.0-SNAPSHOT + + schafkopf-backend-build - - 21 - 21 - UTF-8 - - 1.7.32 - 2.4.0 - 3.5.1 + + + maven-checkstyle-plugin + + + + google_checks.xml + true + true + warning + + + check + + validate + validate + + + org.apache.maven.plugins + 3.3.1 + + + maven-jar-plugin + + + + org.schafkopf.BackendServer + + + + 3.3.0 + - - - schafkopf-backend-build - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.3.1 - - - validate - validate - - google_checks.xml - true - true - warning - - - check - - - - - - maven-jar-plugin - 3.3.0 - - - - org.example.BackendServer - - - - + + maven-compiler-plugin + + true + true + false + + 3.11.0 + - - maven-compiler-plugin - 3.11.0 - - true - true - false - - + + maven-shade-plugin + + + + + + + + + shade + + package + + + org.apache.maven.plugins + 3.5.1 + + + + + + slf4j-api + org.slf4j + ${slf4j.version} + + + slf4j-simple + org.slf4j + ${slf4j.version} + + + + websocket-jetty-api + org.eclipse.jetty.websocket + 11.0.15 + + + + websocket-jetty-server + org.eclipse.jetty.websocket + 11.0.15 + + + jetty-servlets + org.eclipse.jetty + 11.0.15 + + + + websocket-jetty-client + org.eclipse.jetty.websocket + 11.0.15 + + + gson + com.google.code.gson + 2.10.1 + + + dotenv-java + io.github.cdimascio + 3.0.0 + - - org.apache.maven.plugins - maven-shade-plugin - 3.5.1 - - - - - - - - package - - shade - - - - - - - - - in-project - In Project Repo - file://${project.basedir}/lib - - + + + pi4j-core + com.pi4j + ${pi4j.version} + - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.slf4j - slf4j-simple - ${slf4j.version} - - - - org.eclipse.jetty.websocket - websocket-jetty-api - 11.0.15 - - - - org.eclipse.jetty.websocket - websocket-jetty-server - 11.0.15 - - - org.eclipse.jetty - jetty-servlets - 11.0.15 - - - - org.eclipse.jetty.websocket - websocket-jetty-client - 11.0.15 - - - com.google.code.gson - gson - 2.10.1 - - - io.github.cdimascio - dotenv-java - 3.0.0 - - - - - com.pi4j - pi4j-core - ${pi4j.version} - - - - - com.pi4j - pi4j-plugin-raspberrypi - ${pi4j.version} - - - com.pi4j - pi4j-plugin-pigpio - ${pi4j.version} - + + + pi4j-plugin-raspberrypi + com.pi4j + ${pi4j.version} + + + pi4j-plugin-pigpio + com.pi4j + ${pi4j.version} + - - pn532 - pn532-sdk - 1.0.2 - - + + pn532-sdk + pn532 + 1.0.2 + + + org.example + + 4.0.0 + + 3.5.1 + 21 + 21 + + 2.4.0 + UTF-8 + 1.7.32 + + + + + in-project + In Project Repo + file://${project.basedir}/lib + + + + 1.0-SNAPSHOT \ No newline at end of file diff --git a/src/main/java/org/example/BackendServer.java b/src/main/java/org/example/BackendServer.java deleted file mode 100644 index ef68297..0000000 --- a/src/main/java/org/example/BackendServer.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.example; - -import java.net.InetSocketAddress; -import java.net.URI; -import java.time.Duration; -import java.util.EnumSet; - -import jakarta.servlet.DispatcherType; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlets.CrossOriginFilter; -import io.github.cdimascio.dotenv.Dotenv; - -public class BackendServer -{ - private List frontendEndpoints = new ArrayList<>(); - public static void main(String[] args) throws Exception - { - BackendServer server = new BackendServer(); - server.setPort(8080); - server.start(); - server.join(); - } - - private final Server server; - private final ServerConnector connector; - - private final Schafkopf schafkopfGame; - private final KartenLeser nfcLeser; - private CountDownLatch nfcLatch = new CountDownLatch(1); - - private Boolean readingMode = false; - private String uidString = ""; - - public BackendServer() - { - Dotenv dotenv = Dotenv.configure().directory("./").load(); - server = new Server(); - InetSocketAddress address = new InetSocketAddress(dotenv.get("VITE_APP_WEBSOCKET_IP"), 8080); - connector = new ServerConnector(server); - connector.setHost(address.getHostName()); - connector.setPort(address.getPort()); - server.addConnector(connector); - - schafkopfGame = new Schafkopf(this); - nfcLeser = new KartenLeser(this); - - // Setup the basic application "context" for this application at "/" - // This is also known as the handler tree (in jetty speak) - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - server.setHandler(context); - - // Configure CORS settings - configureCORS(context); - - // Configure specific websocket behavior - JettyWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) -> - { - // Configure default max size - wsContainer.setMaxTextMessageSize(65535); - wsContainer.setIdleTimeout(Duration.ofDays(300000)); - // Add websockets - wsContainer.addMapping("/schafkopf-events/*", new FrontendEndpointCreator(this)); - - }); - } - - private void configureCORS(ServletContextHandler context) { - // Enable CORS for all paths - FilterHolder cors = context.addFilter(CrossOriginFilter.class, "/*", null); - - // Configure allowed origins, headers, and methods - cors.setInitParameter("allowedOrigins", "http://192.168.178.126:5173"); - cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin"); - cors.setInitParameter("allowedMethods", "GET,POST,PUT,DELETE,OPTIONS"); - - // Add filter mappings - EnumSet types = EnumSet.of(DispatcherType.REQUEST); - context.addFilter(cors, "*", types); - } - - public void setPort(int port) - { - connector.setPort(port); - } - - public void start() throws Exception - { - server.start(); - } - - public URI getURI() - { - return server.getURI(); - } - - public void stop() throws Exception - { - server.stop(); - } - - public void join() throws InterruptedException - { - server.join(); - } - - public void addFrontendEndpoint(FrontendEndpoint endpoint) { - frontendEndpoints.add(endpoint); - } - - public void removeFrontendEndpoint(FrontendEndpoint endpoint) { - frontendEndpoints.remove(endpoint); - } - - public void sendMessageToAllFrontendEndpoints(String message) { - for (FrontendEndpoint endpoint : frontendEndpoints) { - endpoint.sendMessage(message); - } - } - - public void startSchafkopfGame() { - schafkopfGame.startGame(); - } - - public void stopSchafkopfGame() { - schafkopfGame.stopGame(); - } - - public void showTrumpf() { - schafkopfGame.showTrumpf(); - } - - public void showFarbe() { - schafkopfGame.showFarbe(); - } - public void nfcGelesen(String uidString) { - if(this.uidString.equals(uidString)){ - return; - } - if(!this.readingMode){ - return; - } - - this.uidString = uidString; - nfcLatch.countDown(); - } - - public String waitForCardScan() throws InterruptedException { - this.readingMode = true; - nfcLatch.await(); - this.readingMode = false; - nfcLatch = new CountDownLatch(1); - return this.uidString; - } -} \ No newline at end of file diff --git a/src/main/java/org/example/FrontendEndpoint.java b/src/main/java/org/example/FrontendEndpoint.java deleted file mode 100644 index ec7b08a..0000000 --- a/src/main/java/org/example/FrontendEndpoint.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.example; - -import com.google.gson.Gson; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketAdapter; - -import java.io.IOException; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; - -public class FrontendEndpoint extends WebSocketAdapter { - private final CountDownLatch closureLatch = new CountDownLatch(1); - private BackendServer backendServer; - public FrontendEndpoint(BackendServer backendServer) { - this.backendServer = backendServer; - System.out.println("new FrontendEndpoint"); - } - - @Override - public void onWebSocketConnect(Session session) { - super.onWebSocketConnect(session); - String clientIp = session.getRemoteAddress().toString(); - System.out.println("Endpoint connected from ip: " + clientIp); - - backendServer.addFrontendEndpoint(this); - } - - @Override - public void onWebSocketText(String message) { - super.onWebSocketText(message); - System.out.println("Received TEXT message:" + message); - - if (message.contains("startsimulation")) { - backendServer.startSchafkopfGame(); - } - - if (message.contains("stopsimulation")) { - backendServer.stopSchafkopfGame(); - } - - if(message.contains("showtrumpf")) { - backendServer.showTrumpf(); - } - - if(message.contains("showfarben")) { - backendServer.showFarbe(); - } - } - - @Override - public void onWebSocketClose(int statusCode, String reason) { - super.onWebSocketClose(statusCode, reason); - - backendServer.removeFrontendEndpoint(this); - - System.out.println("Socket Closed: [" + statusCode + "] " + reason); - closureLatch.countDown(); - } - - @Override - public void onWebSocketError(Throwable cause) { - super.onWebSocketError(cause); - cause.printStackTrace(System.err); - } - - public void sendMessage(String message) { - try { - getRemote().sendString(message); - } catch (IOException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/src/main/java/org/example/FrontendEndpointCreator.java b/src/main/java/org/example/FrontendEndpointCreator.java deleted file mode 100644 index f1c27b6..0000000 --- a/src/main/java/org/example/FrontendEndpointCreator.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.example; -import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest; -import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse; -import org.eclipse.jetty.websocket.server.JettyWebSocketCreator; - -public class FrontendEndpointCreator implements JettyWebSocketCreator -{ - private BackendServer backendServer; - public FrontendEndpointCreator(BackendServer backendServer) { - this.backendServer = backendServer; - } - - @Override - public Object createWebSocket(JettyServerUpgradeRequest jettyServerUpgradeRequest, JettyServerUpgradeResponse jettyServerUpgradeResponse) - { - return new FrontendEndpoint(this.backendServer); - } -} \ No newline at end of file diff --git a/src/main/java/org/example/Karte.java b/src/main/java/org/example/Karte.java deleted file mode 100644 index c89ea69..0000000 --- a/src/main/java/org/example/Karte.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.example; - -public class Karte { - private String id; - private String name; - private String farbe; - private String symbol; - private int punkte; - Karte(String id, String name, String farbe, String symbol, int punkte){ - this.id = id; - this.name = name; - this.farbe = farbe; - this.symbol = symbol; - this.punkte = punkte; - } - - public String getId(){ - return this.id; - } - - public String getName(){ - return this.name; - } - - public String getFarbe(){ - return this.farbe; - } - - public String getSymbol() { - return this.symbol; - } -} diff --git a/src/main/java/org/example/KartenLeser.java b/src/main/java/org/example/KartenLeser.java deleted file mode 100644 index 3e13729..0000000 --- a/src/main/java/org/example/KartenLeser.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.example; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.pi4j.Pi4J; -import com.pi4j.io.i2c.I2C; -import mk.hsilomedus.pn532.*; -import mk.hsilomedus.pn532.Pn532SamThread.Pn532SamThreadListener; - -public final class KartenLeser { - - private static BackendServer server; - - public KartenLeser(BackendServer server){ - this.server = server; - - new Thread(() -> { - - new KartenListener().run(); - - }).start(); - } - - - - public static final void main(String[] args) throws IOException { - - } - - private static class KartenListener implements Pn532SamThreadListener { - - @SuppressWarnings("rawtypes") - Pn532SamThread i2cThread = new Pn532SamThread<>(this, new Pn532I2c()); - - - public void run() { - Pn532ContextHelper.initialize(); - i2cThread.start(); - } - - public void close() { - closeThread(i2cThread); - Pn532ContextHelper.shutdown(); - } - - @Override - public void receiveMessage(String message) { - System.out.println(message); - } - - @Override - public void uidReceived(String displayName, byte[] uid) { - server.nfcGelesen(Pn532SamThreadListener.getUidString(uid) ); - } - - @SuppressWarnings("rawtypes") - private void closeThread(Pn532SamThread thread) { - if (thread != null && thread.isAlive()) { - thread.close(); - - try { - thread.join(); - } catch (InterruptedException e) { - System.out.println("Error closing thread: " + e.getMessage()); - Thread.currentThread().interrupt(); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/org/example/KartenUtil.java b/src/main/java/org/example/KartenUtil.java deleted file mode 100644 index ebebed8..0000000 --- a/src/main/java/org/example/KartenUtil.java +++ /dev/null @@ -1,165 +0,0 @@ -package org.example; - -import java.util.ArrayList; -import java.util.List; - -public class KartenUtil { - - public static List getKartenByFarbe(List karten, String farbe) { - List result = new ArrayList<>(); - for (Karte karte : karten) { - if (karte.getFarbe().equalsIgnoreCase(farbe)) { - result.add(karte); - } - } - return result; - } - - public static List getKartenBySymbol(List karten, String symbol) { - List result = new ArrayList<>(); - for (Karte karte : karten) { - if (karte.getSymbol().equalsIgnoreCase(symbol)) { - result.add(karte); - } - } - return result; - } - - public static List initializeSchafKopfCardDeck() { - String[] farben = {"schell", "herz", "blatt", "eichel"}; - String[] symbole = {"6", "7", "8", "9", "u", "o", "k", "x", "a"}; - - int totalCards = farben.length * symbole.length; - List deck = new ArrayList<>(); - - for (String farbe : farben) { - for (String symbol : symbole) { - String cardId = farbe + "_" + symbol; - String cardName = getCardName(farbe, symbol); - int wert = switch (symbol) { - case "6", "9", "8", "7" -> 0; - case "k" -> 4; - case "x" -> 10; - case "a" -> 11; - case "u" -> 2; - case "o" -> 3; - default -> -1; - }; - deck.add(new Karte(cardId, cardName, farbe, symbol, wert)); - } - } - deck.removeAll(KartenUtil.getKartenBySymbol(deck, "6")); - return deck; - } - - private static String getCardName(String farbe, String symbol) { - String cardName = switch (farbe) { - case "schell" -> "Schell"; - case "herz" -> "Herz"; - case "blatt" -> "Blatt"; - case "eichel" -> "Eichel"; - default -> ""; - }; - String prefix = switch (symbol) { - case "6" -> "6"; - case "7" -> "7"; - case "8" -> "8"; - case "9" -> "9"; - case "k" -> "König"; - case "x" -> "10"; - case "a" -> "Ass"; - case "u" -> "Unter"; - case "o" -> "Ober"; - default -> ""; - }; - cardName += " " + prefix; - return cardName; - } - - public static String getIdOfUid(String uid){ - switch (uid){ - case "04A56BB4780000": - return "eichel_7"; - case "04A46BB4780000": - return "eichel_8"; - case "04A26BB4780000": - return "eichel_9"; - case "04A16BB4780000": - return "eichel_x"; - case "049E6BB4780000": - return "eichel_k"; - case "04A86BB4780000": - return "eichel_a"; - case "04A06BB4780000": - return "eichel_u"; - case "049F6BB4780000": - return "eichel_o"; - - case "04F26BB4780000": - return "blatt_7"; - case "04A76BB4780000": - return "blatt_8"; - case "049B6BB4780000": - return "blatt_9"; - case "04996BB4780000": - return "blatt_x"; - case "041CD2C2126F81": - return "blatt_k"; - case "04A96BB4780000": - return "blatt_a"; - case "049A6BB4780000": - return "blatt_u"; - case "049D6BB4780000": - return "blatt_o"; - - case "04936BB4780000": - return "schell_7"; - case "04F697C2126F80": - return "schell_8"; - case "04946BB4780000": - return "schell_9"; - case "04956BB4780000": - return "schell_x"; - case "04986BB4780000": - return "schell_k"; - case "04AA6BB4780000": - return "schell_a"; - case "04966BB4780000": - return "schell_u"; - case "04976BB4780000": - return "schell_o"; - - case "04F36BB4780000": - return "herz_7"; - case "04B06BB4780000": - return "herz_8"; - case "04AF6BB4780000": - return "herz_9"; - case "04AE6BB4780000": - return "herz_x"; - case "04AB6BB4780000": - return "herz_k"; - case "049C6BB4780000": - return "herz_a"; - case "04AD6BB4780000": - return "herz_u"; - case "04AC6BB4780000": - return "herz_o"; - } - return null; - } - - public static Karte getKarteById(String id){ - List kartenList = initializeSchafKopfCardDeck(); - for (Karte karte : kartenList) { - if (karte.getId().equalsIgnoreCase(id)) { - return karte; - } - } - return null; - } - - public static void removeCards(List allCards, List cardsToRemove) { - allCards.removeAll(cardsToRemove); - } -} \ No newline at end of file diff --git a/src/main/java/org/example/Schafkopf.java b/src/main/java/org/example/Schafkopf.java deleted file mode 100644 index e45da80..0000000 --- a/src/main/java/org/example/Schafkopf.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.example; - -import com.google.gson.Gson; -import org.example.spielController.GeierSpielController; -import org.example.spielController.SoloSpielController; -import org.example.spielController.SpielController; -import org.example.spielController.WenzSpielController; - -public class Schafkopf { - private final Karte[] kartenDeck; - private final SpielController spielController = new GeierSpielController( "schell"); - private final BackendServer server; - private boolean gameState = false; - - Schafkopf(BackendServer server) { - this.server = server; - System.out.println("SchaffKopfGame erstellt"); - this.kartenDeck = initializeCardDeck(); - } - - private static String getCardName(String farbe, String symbol) { - String cardName = switch (farbe) { - case "schell" -> "Schell"; - case "herz" -> "Herz"; - case "blatt" -> "Blatt"; - case "eichel" -> "Eichel"; - default -> ""; - }; - String prefix = switch (symbol) { - case "6" -> "6"; - case "7" -> "7"; - case "8" -> "8"; - case "9" -> "9"; - case "k" -> "König"; - case "x" -> "10"; - case "a" -> "Ass"; - case "u" -> "Unter"; - case "o" -> "Ober"; - default -> ""; - }; - cardName += " " + prefix; - return cardName; - } - - public Karte[] initializeCardDeck() { - String[] farben = {"schell", "herz", "blatt", "eichel"}; - String[] symbole = {"6", "7", "8", "9", "k", "x", "a", "u", "o"}; - - int totalCards = farben.length * symbole.length; - Karte[] Deck = new Karte[totalCards]; - - int index = 0; - - for (String farbe : farben) { - for (String symbol : symbole) { - String cardId = farbe + "_" + symbol; - String cardName = getCardName(farbe, symbol); - int wert = switch (symbol) { - case "6", "9", "8", "7" -> 0; - case "k" -> 4; - case "x" -> 10; - case "a" -> 11; - case "u" -> 2; - case "o" -> 3; - default -> -1; - }; - Deck[index] = new Karte(cardId, cardName, farbe, symbol, wert); - index++; - } - } - return Deck; - } - - public void showTrumpf() { - - Gson gson = new Gson(); - for (Karte karte : spielController.getTrumpfKarten()) { - String karteJson = gson.toJson(karte); - server.sendMessageToAllFrontendEndpoints(karteJson); - } - } - - public void showFarbe() { - Gson gson = new Gson(); - for (Karte karte : spielController.getFarbKarten()) { - String karteJson = gson.toJson(karte); - server.sendMessageToAllFrontendEndpoints(karteJson); - } - } - - public void startGame() { - if (gameState) { - System.out.println("Game already started!"); - server.sendMessageToAllFrontendEndpoints("Game already started!"); - } else { - gameState = true; - System.out.println("Start Game"); - server.sendMessageToAllFrontendEndpoints("Start Game"); - } - } - - public void stopGame() { - if (!gameState) { - System.out.println("no active Game!"); - server.sendMessageToAllFrontendEndpoints("no active Game!"); - } else { - gameState = false; - System.out.println("Stop Game"); - server.sendMessageToAllFrontendEndpoints("Stop Game"); - } - - } -} diff --git a/src/main/java/org/example/spielController/GeierSpielController.java b/src/main/java/org/example/spielController/GeierSpielController.java deleted file mode 100644 index 9cce335..0000000 --- a/src/main/java/org/example/spielController/GeierSpielController.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.example.spielController; - -import org.example.Karte; -import org.example.KartenUtil; - -import java.util.ArrayList; -import java.util.List; - -public class GeierSpielController extends SpielController { - public GeierSpielController(String farbe) { - List kartenList = KartenUtil.initializeSchafKopfCardDeck(); - List oberKarten = KartenUtil.getKartenBySymbol(kartenList, "o"); - List farbTrumpfKarten = KartenUtil.getKartenByFarbe(kartenList, farbe); - farbTrumpfKarten.removeAll(KartenUtil.getKartenBySymbol(kartenList, "o")); - farbTrumpfKarten.addAll(oberKarten); - kartenList.removeAll(farbTrumpfKarten); - - this.trumpfKarten = new ArrayList<>(farbTrumpfKarten); - this.farbKarten = new ArrayList<>(kartenList); - } - - public GeierSpielController() { - List kartenList = KartenUtil.initializeSchafKopfCardDeck(); - List oberKarten = KartenUtil.getKartenBySymbol(kartenList, "o"); - - kartenList.removeAll(oberKarten); - - this.trumpfKarten = new ArrayList<>(oberKarten); - this.farbKarten = new ArrayList<>(kartenList); - } -} diff --git a/src/main/java/org/example/spielController/SauSpielController.java b/src/main/java/org/example/spielController/SauSpielController.java deleted file mode 100644 index a63a43a..0000000 --- a/src/main/java/org/example/spielController/SauSpielController.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.example.spielController; -import org.example.Karte; -import org.example.KartenUtil; - -import java.util.List; -import java.util.ArrayList; - -public class SauSpielController extends SpielController{ - - public SauSpielController(){ - List kartenList = KartenUtil.initializeSchafKopfCardDeck(); - List herzKarten = KartenUtil.getKartenByFarbe(kartenList, "herz"); - herzKarten.removeAll(KartenUtil.getKartenBySymbol(kartenList, "u")); - herzKarten.removeAll(KartenUtil.getKartenBySymbol(kartenList, "o")); - - herzKarten.addAll(KartenUtil.getKartenBySymbol(kartenList, "u")); - herzKarten.addAll(KartenUtil.getKartenBySymbol(kartenList, "o")); - - kartenList.removeAll(herzKarten); - - this.trumpfKarten = new ArrayList<>(herzKarten); - this.farbKarten = new ArrayList<>(kartenList); - } -} diff --git a/src/main/java/org/example/spielController/SoloSpielController.java b/src/main/java/org/example/spielController/SoloSpielController.java deleted file mode 100644 index c98a4bf..0000000 --- a/src/main/java/org/example/spielController/SoloSpielController.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.example.spielController; - -import org.example.Karte; -import org.example.KartenUtil; - -import java.util.ArrayList; -import java.util.List; - -public class SoloSpielController extends SpielController { - public SoloSpielController(String farbe) { - List kartenList = KartenUtil.initializeSchafKopfCardDeck(); - List unterKarten = KartenUtil.getKartenBySymbol(kartenList, "u"); - - List farbTrumpfKarten = KartenUtil.getKartenByFarbe(kartenList, farbe); - farbTrumpfKarten.removeAll(KartenUtil.getKartenBySymbol(kartenList, "u")); - farbTrumpfKarten.removeAll(KartenUtil.getKartenBySymbol(kartenList, "o")); - farbTrumpfKarten.addAll(KartenUtil.getKartenBySymbol(kartenList, "u")); - farbTrumpfKarten.addAll(KartenUtil.getKartenBySymbol(kartenList, "o")); - - - - - - - kartenList.removeAll(farbTrumpfKarten); - - this.trumpfKarten = new ArrayList<>(farbTrumpfKarten); - this.farbKarten = new ArrayList<>(kartenList); - } -} diff --git a/src/main/java/org/example/spielController/SpielController.java b/src/main/java/org/example/spielController/SpielController.java deleted file mode 100644 index 263f745..0000000 --- a/src/main/java/org/example/spielController/SpielController.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.example.spielController; - -import org.example.Karte; - -import java.util.List; - -public abstract class SpielController { - protected List trumpfKarten; - protected List farbKarten; - - - - public List getTrumpfKarten() { - return trumpfKarten; - } - - public List getFarbKarten() { - return farbKarten; - } -} diff --git a/src/main/java/org/example/spielController/WenzSpielController.java b/src/main/java/org/example/spielController/WenzSpielController.java deleted file mode 100644 index 73989e9..0000000 --- a/src/main/java/org/example/spielController/WenzSpielController.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.example.spielController; - -import org.example.Karte; -import org.example.KartenUtil; - -import java.util.ArrayList; -import java.util.List; - -public class WenzSpielController extends SpielController { - public WenzSpielController(String farbe) { - List kartenList = KartenUtil.initializeSchafKopfCardDeck(); - List unterKarten = KartenUtil.getKartenBySymbol(kartenList, "u"); - List farbTrumpfKarten = KartenUtil.getKartenByFarbe(kartenList, farbe); - farbTrumpfKarten.removeAll(KartenUtil.getKartenBySymbol(kartenList, "u")); - farbTrumpfKarten.addAll(unterKarten); - kartenList.removeAll(farbTrumpfKarten); - - this.trumpfKarten = new ArrayList<>(farbTrumpfKarten); - this.farbKarten = new ArrayList<>(kartenList); - } - - public WenzSpielController() { - List kartenList = KartenUtil.initializeSchafKopfCardDeck(); - List unterKarten = KartenUtil.getKartenBySymbol(kartenList, "u"); - - kartenList.removeAll(unterKarten); - - this.trumpfKarten = new ArrayList<>(unterKarten); - this.farbKarten = new ArrayList<>(kartenList); - } -} diff --git a/src/main/java/org/schafkopf/BackendServer.java b/src/main/java/org/schafkopf/BackendServer.java new file mode 100644 index 0000000..2b3e217 --- /dev/null +++ b/src/main/java/org/schafkopf/BackendServer.java @@ -0,0 +1,183 @@ +package org.schafkopf; + +import com.google.gson.JsonObject; +import io.github.cdimascio.dotenv.Dotenv; +import jakarta.servlet.DispatcherType; +import java.net.InetSocketAddress; +import java.net.URI; +import java.time.Duration; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.FilterHolder; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlets.CrossOriginFilter; +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; + +/** Main Class that represents the Backend Server. */ +public class BackendServer { + private final Server server; + private final ServerConnector connector; + private final Schafkopf schafkopfGame; + private final KartenLeser nfcLeser; + private final List frontendEndpoints = new ArrayList<>(); + private CountDownLatch nfcLatch = new CountDownLatch(1); + private Boolean readingMode = false; + private String uidString = ""; + + /** Creates an Instance of the Backend Server. */ + public BackendServer() { + Dotenv dotenv = Dotenv.configure().directory("./").load(); + server = new Server(); + InetSocketAddress address = new InetSocketAddress(dotenv.get("VITE_APP_WEBSOCKET_IP"), 8080); + connector = new ServerConnector(server); + connector.setHost(address.getHostName()); + connector.setPort(address.getPort()); + server.addConnector(connector); + + schafkopfGame = new Schafkopf(this); + nfcLeser = new KartenLeser(this); + + // Setup the basic application "context" for this application at "/" + // This is also known as the handler tree (in jetty speak) + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + server.setHandler(context); + + // Configure CORS settings + configureCors(context); + + // Configure specific websocket behavior + JettyWebSocketServletContainerInitializer.configure( + context, + (servletContext, wsContainer) -> { + // Configure default max size + wsContainer.setMaxTextMessageSize(65535); + wsContainer.setIdleTimeout(Duration.ofDays(300000)); + // Add websockets + wsContainer.addMapping("/schafkopf-events/*", new FrontendEndpointCreator(this)); + }); + } + + /** The main entrypoint of the Application. */ + public static void main(String[] args) throws Exception { + BackendServer server = new BackendServer(); + server.setPort(8080); + server.start(); + server.join(); + } + + private void configureCors(ServletContextHandler context) { + // Enable CORS for all paths + FilterHolder cors = context.addFilter(CrossOriginFilter.class, "/*", null); + + // Configure allowed origins, headers, and methods + cors.setInitParameter("allowedOrigins", "*"); + cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin"); + cors.setInitParameter("allowedMethods", "GET,POST,PUT,DELETE,OPTIONS"); + + // Add filter mappings + EnumSet types = EnumSet.of(DispatcherType.REQUEST); + context.addFilter(cors, "*", types); + } + + public void setPort(int port) { + connector.setPort(port); + } + + public void start() throws Exception { + server.start(); + } + + public URI getUri() { + return server.getURI(); + } + + public void stop() throws Exception { + server.stop(); + } + + public void join() throws InterruptedException { + server.join(); + } + + public void addFrontendEndpoint(FrontendEndpoint endpoint) { + frontendEndpoints.add(endpoint); + } + + public void removeFrontendEndpoint(FrontendEndpoint endpoint) { + frontendEndpoints.remove(endpoint); + } + + /** + * Sends Message to all Frontend Instances. + * + * @param message Message to send (String). + */ + public void sendMessageToAllFrontendEndpoints(String message) { + for (FrontendEndpoint endpoint : frontendEndpoints) { + endpoint.sendMessage(message); + } + } + + /** + * Sends Message to all Frontend Instances. + * + * @param message Message to send (JsonObject). + */ + public void sendMessageToAllFrontendEndpoints(JsonObject message) { + for (FrontendEndpoint endpoint : frontendEndpoints) { + endpoint.sendMessage(message.toString()); + } + } + + public void startSchafkopfGame() { + schafkopfGame.startGame(); + } + + public void stopSchafkopfGame() { + schafkopfGame.stopGame(); + } + + public void showTrumpf() { + schafkopfGame.showTrumpf(); + } + + public void showFarbe() { + schafkopfGame.showFarbe(); + } + + public void setGame(String message) { + schafkopfGame.setGame(message); + } + + /** + * checks uid of scanned card and do nothing if Server is not in reading mode. + * + * @param uidString uid to check. + */ + public void nfcGelesen(String uidString) { + if (this.uidString.equals(uidString)) { + return; + } + if (!this.readingMode) { + return; + } + + this.uidString = uidString; + nfcLatch.countDown(); + } + + /** method to call to wait for NFC input. */ + public String waitForCardScan() throws InterruptedException { + this.readingMode = true; + nfcLatch.await(); + Thread.sleep(20); + this.readingMode = false; + nfcLatch = new CountDownLatch(1); + return this.uidString; + } +} diff --git a/src/main/java/org/schafkopf/FrontendEndpoint.java b/src/main/java/org/schafkopf/FrontendEndpoint.java new file mode 100644 index 0000000..03eaf96 --- /dev/null +++ b/src/main/java/org/schafkopf/FrontendEndpoint.java @@ -0,0 +1,77 @@ +package org.schafkopf; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.WebSocketAdapter; + +/** Class that represents one Frontend Connection. */ +public class FrontendEndpoint extends WebSocketAdapter { + private final CountDownLatch closureLatch = new CountDownLatch(1); + private BackendServer backendServer; + + public FrontendEndpoint(BackendServer backendServer) { + this.backendServer = backendServer; + System.out.println("new FrontendEndpoint"); + } + + @Override + public void onWebSocketConnect(Session session) { + super.onWebSocketConnect(session); + String clientIp = session.getRemoteAddress().toString(); + System.out.println("Endpoint connected from ip: " + clientIp); + + backendServer.addFrontendEndpoint(this); + } + + @Override + public void onWebSocketText(String message) { + super.onWebSocketText(message); + System.out.println("Received TEXT message:" + message); + + if (message.contains("startsimulation")) { + backendServer.startSchafkopfGame(); + } + + if (message.contains("stopsimulation")) { + backendServer.stopSchafkopfGame(); + } + + if (message.contains("showtrumpf")) { + backendServer.showTrumpf(); + } + + if (message.contains("showfarben")) { + backendServer.showFarbe(); + } + + if (message.contains("setgame")) { + backendServer.setGame(message); + } + } + + @Override + public void onWebSocketClose(int statusCode, String reason) { + super.onWebSocketClose(statusCode, reason); + + backendServer.removeFrontendEndpoint(this); + + System.out.println("Socket Closed: [" + statusCode + "] " + reason); + closureLatch.countDown(); + } + + @Override + public void onWebSocketError(Throwable cause) { + super.onWebSocketError(cause); + cause.printStackTrace(System.err); + } + + /** send a Message to the connected FrontEnd. */ + public void sendMessage(String message) { + try { + getRemote().sendString(message); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/org/schafkopf/FrontendEndpointCreator.java b/src/main/java/org/schafkopf/FrontendEndpointCreator.java new file mode 100644 index 0000000..d5538ce --- /dev/null +++ b/src/main/java/org/schafkopf/FrontendEndpointCreator.java @@ -0,0 +1,23 @@ +package org.schafkopf; + +import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest; +import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse; +import org.eclipse.jetty.websocket.server.JettyWebSocketCreator; + +/** + * Creater to make new Instances of the FrontendConnection. + */ +public class FrontendEndpointCreator implements JettyWebSocketCreator { + private BackendServer backendServer; + + public FrontendEndpointCreator(BackendServer backendServer) { + this.backendServer = backendServer; + } + + @Override + public Object createWebSocket( + JettyServerUpgradeRequest jettyServerUpgradeRequest, + JettyServerUpgradeResponse jettyServerUpgradeResponse) { + return new FrontendEndpoint(this.backendServer); + } +} diff --git a/src/main/java/org/schafkopf/KartenLeser.java b/src/main/java/org/schafkopf/KartenLeser.java new file mode 100644 index 0000000..3de38ff --- /dev/null +++ b/src/main/java/org/schafkopf/KartenLeser.java @@ -0,0 +1,73 @@ +package org.schafkopf; + +import com.pi4j.io.i2c.I2C; +import java.io.IOException; +import mk.hsilomedus.pn532.Pn532ContextHelper; +import mk.hsilomedus.pn532.Pn532I2c; +import mk.hsilomedus.pn532.Pn532SamThread; +import mk.hsilomedus.pn532.Pn532SamThread.Pn532SamThreadListener; + +/** + * Class that represents the NFC Reader. + */ +public final class KartenLeser { + + private static BackendServer server; + + /** + * Creates an Instance of the KartenLeser. + * + * @param server Backend Server to call methods on. + */ + public KartenLeser(BackendServer server) { + this.server = server; + + new Thread( + () -> { + new KartenListener().run(); + }) + .start(); + } + + public static final void main(String[] args) throws IOException {} + + private static class KartenListener implements Pn532SamThreadListener { + + @SuppressWarnings("rawtypes") + Pn532SamThread i2cThread = new Pn532SamThread<>(this, new Pn532I2c()); + + public void run() { + Pn532ContextHelper.initialize(); + i2cThread.start(); + } + + public void close() { + closeThread(i2cThread); + Pn532ContextHelper.shutdown(); + } + + @Override + public void receiveMessage(String message) { + System.out.println(message); + } + + @Override + public void uidReceived(String displayName, byte[] uid) { + server.nfcGelesen(Pn532SamThreadListener.getUidString(uid)); + } + + @SuppressWarnings("rawtypes") + private void closeThread(Pn532SamThread thread) { + if (thread != null && thread.isAlive()) { + thread.close(); + + try { + thread.join(); + } catch (InterruptedException e) { + System.out.println("Error closing thread: " + e.getMessage()); + Thread.currentThread().interrupt(); + } + } + } + } +} diff --git a/src/main/java/org/schafkopf/Schafkopf.java b/src/main/java/org/schafkopf/Schafkopf.java new file mode 100644 index 0000000..8026e32 --- /dev/null +++ b/src/main/java/org/schafkopf/Schafkopf.java @@ -0,0 +1,194 @@ +package org.schafkopf; + +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenUtil; +import org.schafkopf.player.BotPlayer; +import org.schafkopf.player.LocalPlayer; +import org.schafkopf.player.Player; +import org.schafkopf.spielcontroller.FarbGeierController; +import org.schafkopf.spielcontroller.FarbSoloController; +import org.schafkopf.spielcontroller.FarbWenzController; +import org.schafkopf.spielcontroller.GeierController; +import org.schafkopf.spielcontroller.SauSpielController; +import org.schafkopf.spielcontroller.SpielController; +import org.schafkopf.spielcontroller.WenzController; + +/** The main class representing the Schafkopf game. */ +public class Schafkopf { + private final BackendServer server; + + /** The game controller. This is the class that implements the game logic. */ + private SpielController spiel = new SauSpielController(0, KartenFarbe.EICHEL); + + private final Player[] player = { + new BotPlayer(), new LocalPlayer(this), new LocalPlayer(this), new LocalPlayer(this) + }; + + private boolean gameState = false; + private Thread spielThread; + + public Player[] getPlayer() { + return player; + } + + /** + * Constructor for the Schafkopf class. + * + * @param server The backend server associated with the game. + */ + Schafkopf(BackendServer server) { + this.server = server; + System.out.println("SchaffKopfGame erstellt"); + } + + /** Sends all Trumpf Karten of the current GameType to the Frontend. */ + public void showTrumpf() { + server.sendMessageToAllFrontendEndpoints(spiel.getTrumpfKarten().getJson()); + } + + /** Sends all Farb Karten of the current GameType to the Frontend. */ + public void showFarbe() { + server.sendMessageToAllFrontendEndpoints(spiel.getFarbKarten().getJson()); + } + + /** Waits for a Card and returns a Karte Object. */ + public Karte wartetAufKarte() { + String uid = null; + System.out.println("Starte Warten auf Karte"); + try { + uid = server.waitForCardScan(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + Karte karte = KartenUtil.getIdOfUid(uid); + + if (karte == null) { + System.out.println("Ungültige Karte"); + return wartetAufKarte(); + } + server.sendMessageToAllFrontendEndpoints(karte.getJson()); + System.out.println("Karte gescannt: " + karte.getName()); + System.out.println("Beende Warten auf Karte"); + return karte; + } + + /** Set GameState to "started" and start Game Thread. */ + public void startGame() { + if (gameState) { + System.out.println("Game already started!"); + server.sendMessageToAllFrontendEndpoints("Game already started!"); + } else { + gameState = true; + System.out.println("Start Game"); + + // KartenListe botHand = KartenUtil.zieheZufallsHand(8); + KartenListe botHand = new KartenListe(); + botHand.addKarten(Karte.EICHEL_7); + botHand.addKarten(Karte.EICHEL_8); + botHand.addKarten(Karte.EICHEL_9); + botHand.addKarten(Karte.EICHEL_K); + + botHand.addKarten(Karte.EICHEL_X); + botHand.addKarten(Karte.EICHEL_A); + botHand.addKarten(Karte.EICHEL_U); + botHand.addKarten(Karte.EICHEL_O); + for (Player currentPlayer : player) { + if (currentPlayer instanceof BotPlayer botPlayer) { + // Perform actions specific to BotPlayer + botPlayer.setCards(botHand); // Replace with the actual method you want to call + } + } + + server.sendMessageToAllFrontendEndpoints("Start Game"); + server.sendMessageToAllFrontendEndpoints(botHand.getJson()); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + spielThread = new Thread(() -> new Spielablauf(this, spiel)); + + spielThread.start(); + } + } + + /** Set GameState to "stopped" and interrupt Game Thread. */ + public void stopGame() { + if (!gameState) { + System.out.println("no active Game!"); + server.sendMessageToAllFrontendEndpoints("no active Game!"); + } else { + gameState = false; + System.out.println("Stop Game"); + server.sendMessageToAllFrontendEndpoints("Stop Game"); + } + + spielThread.interrupt(); + } + + /** Set GameType. */ + public void setGame(String message) { + System.out.println("Set Game: " + message); + server.sendMessageToAllFrontendEndpoints("Set Game: " + message); + switch (message) { + case "setgame:herzsolo": + this.spiel = new FarbSoloController(0, KartenFarbe.HERZ); + break; + case "setgame:blattsolo": + this.spiel = new FarbSoloController(0, KartenFarbe.BLATT); + break; + case "setgame:eichelsolo": + this.spiel = new FarbSoloController(0, KartenFarbe.EICHEL); + break; + case "setgame:schellsolo": + this.spiel = new FarbSoloController(0, KartenFarbe.SCHELL); + break; + + case "setgame:wenz": + this.spiel = new WenzController(0); + break; + case "setgame:geier": + this.spiel = new GeierController(0); + break; + + case "setgame:eichelwenz": + this.spiel = new FarbWenzController(0, KartenFarbe.EICHEL); + break; + case "setgame:herzwenz": + this.spiel = new FarbWenzController(0, KartenFarbe.HERZ); + break; + case "setgame:blattwenz": + this.spiel = new FarbWenzController(0, KartenFarbe.BLATT); + break; + case "setgame:schellwenz": + this.spiel = new FarbWenzController(0, KartenFarbe.SCHELL); + break; + + case "setgame:eichelgeier": + this.spiel = new FarbGeierController(0, KartenFarbe.EICHEL); + break; + case "setgame:herzgeier": + this.spiel = new FarbGeierController(0, KartenFarbe.HERZ); + break; + case "setgame:blattgeier": + this.spiel = new FarbGeierController(0, KartenFarbe.BLATT); + break; + case "setgame:schellgeier": + this.spiel = new FarbGeierController(0, KartenFarbe.SCHELL); + break; + + case "setgame:sauspiel": + this.spiel = new SauSpielController(0, KartenFarbe.EICHEL); + break; + default: + System.out.println("Ungültiges Spiel"); + } + } + + public BackendServer getServer() { + return this.server; + } +} diff --git a/src/main/java/org/schafkopf/Spielablauf.java b/src/main/java/org/schafkopf/Spielablauf.java new file mode 100644 index 0000000..677c653 --- /dev/null +++ b/src/main/java/org/schafkopf/Spielablauf.java @@ -0,0 +1,75 @@ +package org.schafkopf; + +import org.schafkopf.karte.KartenListe; +import org.schafkopf.player.Player; +import org.schafkopf.spielcontroller.SpielController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** The main class that controlls the game flow. */ +public class Spielablauf { + + private static final Logger logger = LoggerFactory.getLogger(Spielablauf.class); + private final KartenListe gespielteKarten; + + private final KartenListe tischKarten = new KartenListe(); + + private final SpielController spiel; + + private final Player[] players; + + private final Schafkopf schafkopf; + + private int gemachteStiche; + + Spielablauf(Schafkopf schafkopf, SpielController spiel) { + this.schafkopf = schafkopf; + this.spiel = spiel; + this.players = schafkopf.getPlayer(); + gespielteKarten = new KartenListe(); + gemachteStiche = 0; + try { + einStich(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** Method to Handle flow of one Game. */ + public void einStich() throws InterruptedException { + logger.info("Starte Stiche"); + int rauskommer = 0; + while (gemachteStiche < 8) { + schafkopf.getServer().sendMessageToAllFrontendEndpoints(gespielteKarten.getJson()); + logger.info("Stich: {}", gemachteStiche); + for (int i = 0; i < 4; i++) { + schafkopf.getServer().sendMessageToAllFrontendEndpoints(tischKarten.getJson()); + int nextPlayer = (i + rauskommer) % 4; + + logger.info("Spieler ist dran: {}", nextPlayer); + + tischKarten.addKarten(players[nextPlayer].play(spiel, tischKarten)); + schafkopf.getServer().sendMessageToAllFrontendEndpoints(tischKarten.getJson()); + } + schafkopf.getServer().sendMessageToAllFrontendEndpoints(tischKarten.getJson()); + int stichSpieler = SpielController.welcheKarteSticht(tischKarten); + + + + Thread.sleep(2000); + logger.info("Stiche ende"); + + rauskommer = (rauskommer + stichSpieler) % 4; + logger.warn("Karte sticht: {}", rauskommer); + //rauskommer = 0; + + gespielteKarten.addKarten(tischKarten); + + tischKarten.clear(); + + gemachteStiche++; + } + schafkopf.getServer().sendMessageToAllFrontendEndpoints(gespielteKarten.getJson()); + schafkopf.stopGame(); + } +} diff --git a/src/main/java/org/schafkopf/karte/Karte.java b/src/main/java/org/schafkopf/karte/Karte.java new file mode 100644 index 0000000..ef93bdf --- /dev/null +++ b/src/main/java/org/schafkopf/karte/Karte.java @@ -0,0 +1,85 @@ +package org.schafkopf.karte; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +/** enum to represent all cards in the game. */ +public enum Karte { + EICHEL_7(KartenFarbe.EICHEL, KartenSymbol.SEVEN), + EICHEL_8(KartenFarbe.EICHEL, KartenSymbol.EIGHT), + EICHEL_9(KartenFarbe.EICHEL, KartenSymbol.NINE), + EICHEL_X(KartenFarbe.EICHEL, KartenSymbol.TEN), + EICHEL_K(KartenFarbe.EICHEL, KartenSymbol.KOENIG), + EICHEL_A(KartenFarbe.EICHEL, KartenSymbol.ASS), + EICHEL_U(KartenFarbe.EICHEL, KartenSymbol.UNTER), + EICHEL_O(KartenFarbe.EICHEL, KartenSymbol.OBER), + BLATT_7(KartenFarbe.BLATT, KartenSymbol.SEVEN), + BLATT_8(KartenFarbe.BLATT, KartenSymbol.EIGHT), + BLATT_9(KartenFarbe.BLATT, KartenSymbol.NINE), + BLATT_X(KartenFarbe.BLATT, KartenSymbol.TEN), + BLATT_K(KartenFarbe.BLATT, KartenSymbol.KOENIG), + BLATT_A(KartenFarbe.BLATT, KartenSymbol.ASS), + BLATT_U(KartenFarbe.BLATT, KartenSymbol.UNTER), + BLATT_O(KartenFarbe.BLATT, KartenSymbol.OBER), + SCHELL_7(KartenFarbe.SCHELL, KartenSymbol.SEVEN), + SCHELL_8(KartenFarbe.SCHELL, KartenSymbol.EIGHT), + SCHELL_9(KartenFarbe.SCHELL, KartenSymbol.NINE), + SCHELL_X(KartenFarbe.SCHELL, KartenSymbol.TEN), + SCHELL_K(KartenFarbe.SCHELL, KartenSymbol.KOENIG), + SCHELL_A(KartenFarbe.SCHELL, KartenSymbol.ASS), + SCHELL_U(KartenFarbe.SCHELL, KartenSymbol.UNTER), + SCHELL_O(KartenFarbe.SCHELL, KartenSymbol.OBER), + HERZ_7(KartenFarbe.HERZ, KartenSymbol.SEVEN), + HERZ_8(KartenFarbe.HERZ, KartenSymbol.EIGHT), + HERZ_9(KartenFarbe.HERZ, KartenSymbol.NINE), + HERZ_X(KartenFarbe.HERZ, KartenSymbol.TEN), + HERZ_K(KartenFarbe.HERZ, KartenSymbol.KOENIG), + HERZ_A(KartenFarbe.HERZ, KartenSymbol.ASS), + HERZ_U(KartenFarbe.HERZ, KartenSymbol.UNTER), + HERZ_O(KartenFarbe.HERZ, KartenSymbol.OBER); + + private final String id; + private final KartenFarbe farbe; + private final KartenSymbol symbol; + + private final String displayName; + + private final int punkte; + + Karte(KartenFarbe farbe, KartenSymbol symbol) { + this.farbe = farbe; + this.symbol = symbol; + this.id = this.name().toLowerCase(); + this.displayName = farbe.getDisplayName() + " " + symbol.getDisplayName(); + this.punkte = symbol.getValue(); + } + + public String getId() { + return this.id; + } + + public String getName() { + return this.displayName; + } + + public KartenFarbe getFarbe() { + return this.farbe; + } + + public KartenSymbol getSymbol() { + return this.symbol; + } + + public int getPunkte() { + return this.punkte; + } + + /** get the Card as a Json Object. */ + public JsonObject getJson() { + Gson gson = new Gson(); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("card", gson.toJsonTree(this)); + + return jsonObject; + } +} diff --git a/src/main/java/org/schafkopf/karte/KartenFarbe.java b/src/main/java/org/schafkopf/karte/KartenFarbe.java new file mode 100644 index 0000000..cfd7e84 --- /dev/null +++ b/src/main/java/org/schafkopf/karte/KartenFarbe.java @@ -0,0 +1,21 @@ +package org.schafkopf.karte; + +/** + * Enum for all possible Card Colors. + */ +public enum KartenFarbe { + EICHEL("Eichel"), + BLATT("Blatt"), + HERZ("Herz"), + SCHELL("Schell"); + + private final String displayName; + + KartenFarbe(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } +} diff --git a/src/main/java/org/schafkopf/karte/KartenListe.java b/src/main/java/org/schafkopf/karte/KartenListe.java new file mode 100644 index 0000000..ba5008d --- /dev/null +++ b/src/main/java/org/schafkopf/karte/KartenListe.java @@ -0,0 +1,203 @@ +package org.schafkopf.karte; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; + +/** + * A Class that represents a list of Cards. + */ +public class KartenListe { + private List kartenListe; + + public KartenListe() { + this.kartenListe = new ArrayList<>(); + } + + public KartenListe(KartenListe liste) { + this.kartenListe = new ArrayList<>(liste.getKartenListe()); + } + + public List getKartenListe() { + return this.kartenListe; + } + + /** + * A Class that represents a list of Cards. + */ + public void addKarten(Karte karte) { + if (!this.containsKarte(karte)) { + this.kartenListe.add(karte); + return; + } + throw new RuntimeException("Karte bereits vorhanden: " + karte.getName()); + } + + // methoden zum hinzufügen von karten + + /** + * A Class that represents a list of Cards. + */ + public void addKarten(KartenListe karten) { + for (Karte karte : karten.getKartenListe()) { + this.addKarten(karte); + } + } + + /** + * A Class that represents a list of Cards. + */ + public KartenListe removeKarten(KartenListe karten) { + KartenListe result = new KartenListe(); + for (Karte karteWeg : karten.getKartenListe()) { + for (Karte karte : this.kartenListe) { + if (karte.getId().equals(karteWeg.getId())) { + result.addKarten(karte); + break; + } + } + } + this.kartenListe.removeAll(result.getKartenListe()); + return result; + } + + // methoden zum entfernen von karten + + /** + * A Class that represents a list of Cards. + */ + public KartenListe removeKarten(KartenFarbe farbe) { + KartenListe result = new KartenListe(); + for (Karte karte : this.kartenListe) { + if (karte.getFarbe().equals(farbe)) { + result.addKarten(karte); + } + } + this.kartenListe.removeAll(result.getKartenListe()); + return result; + } + + /** + * A Class that represents a list of Cards. + */ + public KartenListe removeKarten(KartenSymbol symbol) { + KartenListe result = new KartenListe(); + for (Karte karte : this.kartenListe) { + if (karte.getSymbol().equals(symbol)) { + result.addKarten(karte); + } + } + this.kartenListe.removeAll(result.getKartenListe()); + return result; + } + + /** + * A Class that represents a list of Cards. + */ + public Karte removeKarten(Karte karteToRemove) { + for (Karte karte : this.kartenListe) { + if (karte.getId().equals(karteToRemove.getId())) { + this.kartenListe.remove(karte); + return karte; + } + } + return null; + } + + /** + * A Class that represents a list of Cards. + */ + public Karte removeKarten(String idToRemove) { + for (Karte karte : this.kartenListe) { + if (karte.getId().equals(idToRemove)) { + this.kartenListe.remove(karte); + return karte; + } + } + return null; + } + + /** + * A Class that represents a list of Cards. + */ + private boolean containsKarte(Karte karte) { + for (Karte karteInListe : this.kartenListe) { + if (karteInListe.getId().equals(karte.getId())) { + return true; + } + } + return false; + } + + // get Karten + + /** + * A Class that represents a list of Cards. + */ + public KartenListe getKarten(KartenFarbe farbe) { + KartenListe result = new KartenListe(); + for (Karte karte : this.kartenListe) { + if (karte.getFarbe().equals(farbe)) { + result.addKarten(karte); + } + } + return result; + } + + /** + * A Class that represents a list of Cards. + */ + public KartenListe getKarten(KartenSymbol symbol) { + KartenListe result = new KartenListe(); + for (Karte karte : this.kartenListe) { + if (karte.getSymbol().equals(symbol)) { + result.addKarten(karte); + } + } + return result; + } + + /** + * A Class that represents a list of Cards. + */ + public JsonObject getJson() { + Gson gson = new Gson(); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("cards", gson.toJsonTree(this.kartenListe)); + + return jsonObject; + } + + public boolean isEmpty() { + return this.kartenListe.isEmpty(); + } + + public Karte getLast() { + return this.kartenListe.getLast(); + } + + public Karte getByIndex(int index) { + return this.kartenListe.get(index); + } + + public int size() { + return this.kartenListe.size(); + } + + /** + * A Class that represents a list of Cards. + */ + public int indexOf(Karte karte) { + for (Karte karteInListe : this.kartenListe) { + if (karteInListe.getId().equals(karte.getId())) { + return this.kartenListe.indexOf(karteInListe); + } + } + return -1; + } + + public void clear() { + this.kartenListe.clear(); + } +} diff --git a/src/main/java/org/schafkopf/karte/KartenSymbol.java b/src/main/java/org/schafkopf/karte/KartenSymbol.java new file mode 100644 index 0000000..b8e2c91 --- /dev/null +++ b/src/main/java/org/schafkopf/karte/KartenSymbol.java @@ -0,0 +1,38 @@ +package org.schafkopf.karte; + +/** + * Enum for all possible Card Symbols. + */ +public enum KartenSymbol { + SIX("6", "6", 0), + SEVEN("7", "7", 0), + EIGHT("8", "8", 0), + NINE("9", "9", 0), + UNTER("u", "Unter", 2), + OBER("o", "Ober", 3), + KOENIG("k", "König", 4), + TEN("x", "10", 10), + ASS("a", "Ass", 11); + + private final String displayName; + private final String id; + private final int value; + + KartenSymbol(String id, String displayName, int value) { + this.displayName = displayName; + this.value = value; + this.id = id; + } + + public String getDisplayName() { + return displayName; + } + + public int getValue() { + return value; + } + + public String getId() { + return id; + } +} diff --git a/src/main/java/org/schafkopf/karte/KartenUtil.java b/src/main/java/org/schafkopf/karte/KartenUtil.java new file mode 100644 index 0000000..b92080d --- /dev/null +++ b/src/main/java/org/schafkopf/karte/KartenUtil.java @@ -0,0 +1,82 @@ +package org.schafkopf.karte; + +import java.util.Random; + +/** Class that brings usefully functions for Card/s. */ +public class KartenUtil { + + /** initialize a normal Card Deck. It will be in the standard order. */ + public static KartenListe initializeSchafKopfCardDeck() { + KartenListe deck = new KartenListe(); + + for (Karte karte : Karte.values()) { + deck.addKarten(karte); + } + + deck.removeKarten(KartenSymbol.SIX); + return deck; + } + + /** + * Create a List of Random Cards. + * + * @param anzahl count of random cards. + */ + public static KartenListe zieheZufallsHand(int anzahl) { + KartenListe karten = initializeSchafKopfCardDeck(); + KartenListe gezogeneKarten = new KartenListe(); + Random random = new Random(); + + // Ziehe zufällige Karten + for (int i = 0; i < anzahl; i++) { + int zufallsIndex = random.nextInt(karten.size()); + Karte gezogeneKarte = karten.getByIndex(zufallsIndex); + gezogeneKarten.addKarten(gezogeneKarte); + karten.removeKarten(gezogeneKarte); + } + return gezogeneKarten; + } + + /** + * converts Uid from a NFC Card to a card ID. + * + * @param uid uId to get the Card ID from. + */ + public static Karte getIdOfUid(String uid) { + return switch (uid) { + case "04A56BB4780000" -> Karte.EICHEL_7; + case "04A46BB4780000" -> Karte.EICHEL_8; + case "04A26BB4780000" -> Karte.EICHEL_9; + case "04A16BB4780000" -> Karte.EICHEL_X; + case "049E6BB4780000" -> Karte.EICHEL_K; + case "04A86BB4780000" -> Karte.EICHEL_A; + case "04A06BB4780000" -> Karte.EICHEL_U; + case "049F6BB4780000" -> Karte.EICHEL_O; + case "04F26BB4780000" -> Karte.BLATT_7; + case "04A76BB4780000" -> Karte.BLATT_8; + case "049B6BB4780000" -> Karte.BLATT_9; + case "04996BB4780000" -> Karte.BLATT_X; + case "041CD2C2126F81" -> Karte.BLATT_K; + case "04A96BB4780000" -> Karte.BLATT_A; + case "049A6BB4780000" -> Karte.BLATT_U; + case "049D6BB4780000" -> Karte.BLATT_O; + case "04936BB4780000" -> Karte.SCHELL_7; + case "04F697C2126F80" -> Karte.SCHELL_8; + case "04946BB4780000" -> Karte.SCHELL_9; + case "04956BB4780000" -> Karte.SCHELL_X; + case "04986BB4780000" -> Karte.SCHELL_K; + case "04AA6BB4780000" -> Karte.SCHELL_A; + case "04966BB4780000" -> Karte.SCHELL_U; + case "04976BB4780000" -> Karte.SCHELL_O; + case "04F36BB4780000" -> Karte.HERZ_7; + case "04B06BB4780000" -> Karte.HERZ_8; + case "04AF6BB4780000" -> Karte.HERZ_9; + case "04AE6BB4780000" -> Karte.HERZ_X; + case "04AB6BB4780000" -> Karte.HERZ_K; + case "049C6BB4780000" -> Karte.HERZ_A; + case "04AD6BB4780000" -> Karte.HERZ_U; + case "04AC6BB4780000" -> Karte.HERZ_O; + default -> null; + }; + } +} diff --git a/src/main/java/org/schafkopf/player/BotPlayer.java b/src/main/java/org/schafkopf/player/BotPlayer.java new file mode 100644 index 0000000..72e4b04 --- /dev/null +++ b/src/main/java/org/schafkopf/player/BotPlayer.java @@ -0,0 +1,47 @@ +package org.schafkopf.player; + +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; +import org.schafkopf.spielcontroller.SauSpielController; +import org.schafkopf.spielcontroller.SpielController; + +/** + * Player that represents the Bot. + */ +public class BotPlayer extends Player { + + private KartenListe eigeneKarten; + private KartenListe unbekannteKarten = KartenUtil.initializeSchafKopfCardDeck(); + + public BotPlayer() { + // TODO document why this constructor is empty + } + + @Override + public Karte play(SpielController spiel, KartenListe tischKarten) { + + Karte cardIndex = eigeneKarten.getByIndex(spiel.welcheKarteSpielIch(0, + eigeneKarten, + eigeneKarten, + tischKarten)); + + eigeneKarten.removeKarten(cardIndex); + + System.out.println("Eigene Karte legen"); + return cardIndex; + } + + /** + * Set the Cards of the Player. + */ + public void setCards(KartenListe cards) { + System.out.println("Eigene Karte setzen"); + this.eigeneKarten = cards; + this.unbekannteKarten = KartenUtil.initializeSchafKopfCardDeck(); + this.unbekannteKarten.removeKarten(eigeneKarten); + System.out.println("Eigene Karte fertig"); + } +} diff --git a/src/main/java/org/schafkopf/player/LocalPlayer.java b/src/main/java/org/schafkopf/player/LocalPlayer.java new file mode 100644 index 0000000..446da73 --- /dev/null +++ b/src/main/java/org/schafkopf/player/LocalPlayer.java @@ -0,0 +1,25 @@ +package org.schafkopf.player; + +import org.schafkopf.Schafkopf; +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.spielcontroller.SpielController; + +/** + * Player that plays in real life. + */ +public class LocalPlayer extends Player { + + private final Schafkopf schafkopf; + + public LocalPlayer(Schafkopf schafkopf) { + this.schafkopf = schafkopf; + } + + @Override + public Karte play(SpielController spiel, KartenListe tischKarten) { + return schafkopf.wartetAufKarte(); + } +} diff --git a/src/main/java/org/schafkopf/player/Player.java b/src/main/java/org/schafkopf/player/Player.java new file mode 100644 index 0000000..50f69e7 --- /dev/null +++ b/src/main/java/org/schafkopf/player/Player.java @@ -0,0 +1,12 @@ +package org.schafkopf.player; + +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.spielcontroller.SpielController; + +/** + * Class that represents one Player of the game. + */ +public abstract class Player { + public abstract Karte play(SpielController spiel, KartenListe tischKarten); +} diff --git a/src/main/java/org/schafkopf/spielcontroller/FarbGeierController.java b/src/main/java/org/schafkopf/spielcontroller/FarbGeierController.java new file mode 100644 index 0000000..2c410a4 --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/FarbGeierController.java @@ -0,0 +1,35 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; + +/** + * SpielController that implements Logic of a Farb Geier. + */ +public class FarbGeierController extends SoloController { + /** + * Create instance of SpielController. + * + * @param farbe Trumpffarbe of the Farb Geier. + */ + public FarbGeierController(int activePlayer, KartenFarbe farbe) { + super(activePlayer); + KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck(); + KartenListe oberKarten = kartenList.getKarten(KartenSymbol.OBER); + KartenListe farbTrumpfKarten = kartenList.getKarten(farbe); + farbTrumpfKarten.removeKarten(KartenSymbol.OBER); + farbTrumpfKarten.addKarten(oberKarten); + kartenList.removeKarten(farbTrumpfKarten); + + this.trumpfKarten = new KartenListe(farbTrumpfKarten); + this.farbKarten = new KartenListe(kartenList); + } + + public int welcheKarteSpielIch(int meinePosition, + KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) { + return 0; + } + +} diff --git a/src/main/java/org/schafkopf/spielcontroller/FarbSoloController.java b/src/main/java/org/schafkopf/spielcontroller/FarbSoloController.java new file mode 100644 index 0000000..690ec62 --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/FarbSoloController.java @@ -0,0 +1,39 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; + +/** + * SpielController that implements Logic of a Farb Solo. + */ +public class FarbSoloController extends SoloController { + /** + * Create instance of SpielController. + * + * @param farbe Trumpffarbe of the Farb Solo. + */ + public FarbSoloController(int activePlayer, KartenFarbe farbe) { + super(activePlayer); + KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck(); + KartenListe unterKarten = kartenList.getKarten(KartenSymbol.UNTER); + + KartenListe farbTrumpfKarten = kartenList.getKarten(farbe); + farbTrumpfKarten.removeKarten(KartenSymbol.UNTER); + farbTrumpfKarten.removeKarten(KartenSymbol.OBER); + farbTrumpfKarten.addKarten(kartenList.getKarten(KartenSymbol.UNTER)); + farbTrumpfKarten.addKarten(kartenList.getKarten(KartenSymbol.OBER)); + + kartenList.removeKarten(farbTrumpfKarten); + + this.trumpfKarten = new KartenListe(farbTrumpfKarten); + this.farbKarten = new KartenListe(kartenList); + } + + public int welcheKarteSpielIch(int meinePosition, + KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) { + return 0; + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/FarbWenzController.java b/src/main/java/org/schafkopf/spielcontroller/FarbWenzController.java new file mode 100644 index 0000000..0ff4c8c --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/FarbWenzController.java @@ -0,0 +1,35 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; + +/** + * SpielController that implements Logic of a Farb Wenz. + */ +public class FarbWenzController extends SoloController { + /** + * Create instance of SpielController. + * + * @param farbe Trumpffarbe of the Farb Wenz. + */ + public FarbWenzController(int activePlayer, KartenFarbe farbe) { + super(activePlayer); + KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck(); + KartenListe unterKarten = kartenList.getKarten(KartenSymbol.UNTER); + KartenListe farbTrumpfKarten = kartenList.getKarten(farbe); + farbTrumpfKarten.removeKarten(KartenSymbol.UNTER); + farbTrumpfKarten.addKarten(unterKarten); + kartenList.removeKarten(farbTrumpfKarten); + + this.trumpfKarten = new KartenListe(farbTrumpfKarten); + this.farbKarten = new KartenListe(kartenList); + } + + public int welcheKarteSpielIch(int meinePosition, + KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) { + return 0; + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/GeierController.java b/src/main/java/org/schafkopf/spielcontroller/GeierController.java new file mode 100644 index 0000000..ee59025 --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/GeierController.java @@ -0,0 +1,25 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; + +/** + * SpielController that implements Logic of a Geier Game. + */ +public class GeierController extends GeierWenzController { + /** + * Create instance of Geier Game. + */ + public GeierController(int activePlayer) { + super(activePlayer); + KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck(); + KartenListe oberKarten = kartenList.getKarten(KartenSymbol.OBER); + + kartenList.removeKarten(oberKarten); + + this.trumpfKarten = new KartenListe(oberKarten); + this.farbKarten = new KartenListe(kartenList); + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/GeierWenzController.java b/src/main/java/org/schafkopf/spielcontroller/GeierWenzController.java new file mode 100644 index 0000000..6a4586b --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/GeierWenzController.java @@ -0,0 +1,21 @@ +package org.schafkopf.spielcontroller; + +import java.util.List; +import org.schafkopf.karte.Karte; +import org.schafkopf.karte.KartenListe; + +/** + * SpielController that implements Logic of a Geier/Wenz Game. + */ +public class GeierWenzController extends SoloController { + + public GeierWenzController(int activePlayer) { + super(activePlayer); + } + + @Override + public int welcheKarteSpielIch(int meinePosition, KartenListe gespielteKarten, + KartenListe meineHand, KartenListe tischKarten) { + return 0; + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/SauSpielController.java b/src/main/java/org/schafkopf/spielcontroller/SauSpielController.java new file mode 100644 index 0000000..20eb24e --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/SauSpielController.java @@ -0,0 +1,66 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; + +/** + * SpielController that implements Logic of a Sau Spiel Game. + */ +public class SauSpielController extends StandardController { + + KartenFarbe suchFarbe; + boolean istSpieler; + + /** + * Class that represents one Card of the game. + */ + public SauSpielController(int activePlayer, KartenFarbe farbe) { + super(activePlayer); + this.suchFarbe = suchFarbe; + this.istSpieler = istSpieler; + } + + /** + * choose witch Card should be played with the right Game logic. + */ + public int welcheKarteSpielIch(int meinePosition, + KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) { + System.out.println("Ich spiele eine Karte Sauspiel"); + + int spielerNummer = tischKarten.size(); + + if (istSpieler && tischKarten.getLast().getFarbe().equals(suchFarbe)) { + return farbeZugeben(meineHand, suchFarbe, 2); + } + + switch (spielerNummer) { + case 0: + if (istSpieler) { + return meineHand.size() - 1; + } else { + return 0; + } + case 1: + if (istSpieler) { + return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 2); + } else { + return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 0); + } + case 2: + if (istSpieler) { + return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 2); + } else { + return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 0); + } + case 3: + if (istSpieler) { + return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 2); + } else { + return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 0); + } + default: + System.out.println("Ungültige SpielerNummer"); + } + return 0; + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/SoloController.java b/src/main/java/org/schafkopf/spielcontroller/SoloController.java new file mode 100644 index 0000000..11ad24d --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/SoloController.java @@ -0,0 +1,18 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenListe; + +/** + * abstract Class that represents Logic of a Solo like Game. + */ +public abstract class SoloController extends SpielController { + + SoloController(int activePlayer) { + super(activePlayer); + } + + public int welcheKarteSpielIch( + KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) { + return 0; + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/SpielController.java b/src/main/java/org/schafkopf/spielcontroller/SpielController.java new file mode 100644 index 0000000..24c6ed1 --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/SpielController.java @@ -0,0 +1,116 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenUtil; + +/** Base Class of Game Controllers. */ +public abstract class SpielController { + protected static KartenListe trumpfKarten; + protected static KartenListe farbKarten; + + protected static int activePlayer; + + public SpielController(int activePlayer) { + this.activePlayer = activePlayer; + } + + /** + * Create instance of SpielController. + * + * @param meineHand Cards one Player holds. + * @param farbe color the Player has to play. + * @param mode Mode the player chooses a Card if multiple are available. + */ + public static int farbeZugeben(KartenListe meineHand, KartenFarbe farbe, int mode) { + KartenListe farbKarten = meineHand.getKarten(farbe); + farbKarten.removeKarten(trumpfKarten); + if (farbKarten.size() == 1) { + return meineHand.indexOf(farbKarten.getByIndex(0)); + } + if (farbKarten.size() > 1) { + switch (mode) { + case 0: + return 0; + case 1: + return meineHand.indexOf(farbKarten.getLast()); + case 2: + return meineHand.indexOf(farbKarten.getLast()); + default: + return 0; + } + } + if (farbKarten.isEmpty()) { + switch (mode) { + case 0: + return 0; + case 1: + return 0; + case 2: + return meineHand.size() - 1; + default: + return 0; + } + } + return 0; + } + + /** + * sorts Cards, so they are in the right order for the active game. + * + * @param karten Trumpffarbe of the Farb Geier. + */ + public static void sortiereKarten(KartenListe karten) { + KartenListe kartenReihenfolge = new KartenListe(farbKarten); + kartenReihenfolge.addKarten(trumpfKarten); + + KartenListe kartenListe = KartenUtil.initializeSchafKopfCardDeck(); + + kartenListe.removeKarten(karten); + kartenReihenfolge.removeKarten(kartenListe); + + karten.clear(); + karten.addKarten(kartenReihenfolge); + } + + /** + * checks, which card has the highest strength and will win one Stich. + * + * @param karten Cards to check. + */ + public static int welcheKarteSticht(KartenListe karten) { + KartenListe kartenNew = new KartenListe(karten); + sortiereKarten(kartenNew); + KartenListe farbTischKarten = kartenNew.removeKarten(trumpfKarten); + System.out.println("trumpfKarten:"); + System.out.println(trumpfKarten.getJson()); + + if (!farbTischKarten.isEmpty()) { + System.out.println("trumpfkarten:"); + System.out.println(farbTischKarten.getJson()); + return karten.indexOf(farbTischKarten.getLast()); + } else { + KartenFarbe firstColor = karten.getByIndex(0).getFarbe(); + KartenListe firstColorCards = kartenNew.removeKarten(firstColor); + + System.out.println("firstcolor:"); + System.out.println(firstColorCards.getJson()); + + return karten.indexOf(firstColorCards.getLast()); + } + } + + public abstract int welcheKarteSpielIch( + int meinePosition, + KartenListe gespielteKarten, + KartenListe meineHand, + KartenListe tischKarten); + + public KartenListe getTrumpfKarten() { + return trumpfKarten; + } + + public KartenListe getFarbKarten() { + return farbKarten; + } +} diff --git a/src/main/java/org/schafkopf/spielcontroller/StandardController.java b/src/main/java/org/schafkopf/spielcontroller/StandardController.java new file mode 100644 index 0000000..2358008 --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/StandardController.java @@ -0,0 +1,31 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenFarbe; +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; + +/** + * SpielController that has the standard Card Deck for Sauspiel, Bettel und Co. + */ +public abstract class StandardController extends SpielController { + + StandardController(int activePlayer) { + super(activePlayer); + KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck(); + KartenListe herzKarten = kartenList.getKarten(KartenFarbe.HERZ); + herzKarten.removeKarten(KartenSymbol.UNTER); + herzKarten.removeKarten(KartenSymbol.OBER); + + herzKarten.addKarten(kartenList.getKarten(KartenSymbol.UNTER)); + herzKarten.addKarten(kartenList.getKarten(KartenSymbol.OBER)); + + kartenList.removeKarten(herzKarten); + + this.trumpfKarten = new KartenListe(herzKarten); + this.farbKarten = new KartenListe(kartenList); + } + + public abstract int welcheKarteSpielIch(int meinePosition, + KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten); +} diff --git a/src/main/java/org/schafkopf/spielcontroller/WenzController.java b/src/main/java/org/schafkopf/spielcontroller/WenzController.java new file mode 100644 index 0000000..70cff99 --- /dev/null +++ b/src/main/java/org/schafkopf/spielcontroller/WenzController.java @@ -0,0 +1,25 @@ +package org.schafkopf.spielcontroller; + +import org.schafkopf.karte.KartenListe; +import org.schafkopf.karte.KartenSymbol; +import org.schafkopf.karte.KartenUtil; + +/** + * SpielController that implements Logic of a Wenz Game. + */ +public class WenzController extends GeierWenzController { + /** + * Create instance of Wenz Game. + */ + public WenzController(int activePlayer) { + super(activePlayer); + this.activePlayer = activePlayer; + KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck(); + KartenListe unterKarten = kartenList.getKarten(KartenSymbol.UNTER); + + kartenList.removeKarten(unterKarten); + + this.trumpfKarten = new KartenListe(unterKarten); + this.farbKarten = new KartenListe(kartenList); + } +}