Spielablauf (#11)

* added Spielablauf and added various things like Card classes etc.
Co-authored-by: Tobias <tibistruppi.te@gmail.com>
This commit is contained in:
Valentin Heiserer
2023-11-28 22:27:25 +01:00
committed by GitHub
parent da81e7bac0
commit 1376fe645a
43 changed files with 2341 additions and 936 deletions

21
.github/workflows/maven.yml vendored Normal file
View File

@@ -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

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,598 @@
<?xml version="1.0" encoding="UTF-8"?>
<code_scheme name="GoogleStyle">
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true"/>
<option name="LAYOUT_SETTINGS">
<value>
<option name="INSERT_BLANK_LINE_BEFORE_TAG" value="false"/>
</value>
</option>
</AndroidXmlCodeStyleSettings>
<JSCodeStyleSettings>
<option name="INDENT_CHAINED_CALLS" value="false"/>
</JSCodeStyleSettings>
<Objective-C>
<option name="INDENT_NAMESPACE_MEMBERS" value="0"/>
<option name="INDENT_C_STRUCT_MEMBERS" value="2"/>
<option name="INDENT_CLASS_MEMBERS" value="2"/>
<option name="INDENT_VISIBILITY_KEYWORDS" value="1"/>
<option name="INDENT_INSIDE_CODE_BLOCK" value="2"/>
<option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true"/>
<option name="FUNCTION_PARAMETERS_WRAP" value="5"/>
<option name="FUNCTION_CALL_ARGUMENTS_WRAP" value="5"/>
<option name="TEMPLATE_CALL_ARGUMENTS_WRAP" value="5"/>
<option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE" value="true"/>
<option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false"/>
<option name="SPACE_BEFORE_SUPERCLASS_COLON" value="false"/>
</Objective-C>
<Objective-C-extensions>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod"/>
</class>
<extensions>
<pair header="h" source="cc"/>
<pair header="h" source="c"/>
</extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl"/>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function"/>
</file>
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK"/>
<option name="RELEASE_STYLE" value="IVAR"/>
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE"/>
</Objective-C-extensions>
<Python>
<option name="USE_CONTINUATION_INDENT_FOR_ARGUMENTS" value="true"/>
</Python>
<TypeScriptCodeStyleSettings>
<option name="INDENT_CHAINED_CALLS" value="false"/>
</TypeScriptCodeStyleSettings>
<XML>
<option name="XML_ALIGN_ATTRIBUTES" value="false"/>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
</XML>
<codeStyleSettings language="CSS">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="ECMA Script Level 4">
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="EXTENDS_LIST_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<option name="PARENT_SETTINGS_INSTALLED" value="true"/>
</codeStyleSettings>
<codeStyleSettings language="HTML">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_RESOURCES" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="EXTENDS_LIST_WRAP" value="1"/>
<option name="THROWS_KEYWORD_WRAP" value="1"/>
<option name="METHOD_CALL_CHAIN_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="WRAP_COMMENTS" value="true"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<option name="PARENT_SETTINGS_INSTALLED" value="true"/>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
<option name="RIGHT_MARGIN" value="80"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<option name="PARENT_SETTINGS_INSTALLED" value="true"/>
</codeStyleSettings>
<codeStyleSettings language="PROTO">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="2"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
<option name="RIGHT_MARGIN" value="80"/>
</codeStyleSettings>
<codeStyleSettings language="protobuf">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="2"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
<option name="RIGHT_MARGIN" value="80"/>
</codeStyleSettings>
<codeStyleSettings language="Python">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
<option name="RIGHT_MARGIN" value="80"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="PARENT_SETTINGS_INSTALLED" value="true"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
</codeStyleSettings>
<codeStyleSettings language="SASS">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="SCSS">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="TypeScript">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:.*Style</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_width</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_weight</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_margin</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginTop</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginBottom</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginStart</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginEnd</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginLeft</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_marginRight</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:padding</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingTop</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingBottom</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingStart</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingEnd</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingLeft</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:paddingRight</NAME>
<XML_ATTRIBUTE/>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res-auto</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/tools</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="2"/>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="ObjectiveC">
<indentOptions>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
</indentOptions>
<option name="RIGHT_MARGIN" value="80"/>
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
<option name="BLANK_LINES_BEFORE_IMPORTS" value="0"/>
<option name="BLANK_LINES_AFTER_IMPORTS" value="0"/>
<option name="BLANK_LINES_AROUND_CLASS" value="0"/>
<option name="BLANK_LINES_AROUND_METHOD" value="0"/>
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0"/>
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="false"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ASSIGNMENT_WRAP" value="1"/>
</codeStyleSettings>
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="INDENT_SIZE" value="2"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="2"/>
<option name="USE_TAB_CHARACTER" value="false"/>
<option name="SMART_TABS" value="false"/>
<option name="LABEL_INDENT_SIZE" value="0"/>
<option name="LABEL_INDENT_ABSOLUTE" value="false"/>
<option name="USE_RELATIVE_INDENTS" value="false"/>
</value>
</option>
<option name="INSERT_INNER_CLASS_IMPORTS" value="true"/>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999"/>
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value/>
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<emptyLine/>
<package name="" static="true" withSubpackages="true"/>
<package name="" static="false" withSubpackages="true"/>
</value>
</option>
<option name="RIGHT_MARGIN" value="100"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_P_AT_EMPTY_LINES" value="false"/>
<option name="JD_KEEP_EMPTY_PARAMETER" value="false"/>
<option name="JD_KEEP_EMPTY_EXCEPTION" value="false"/>
<option name="JD_KEEP_EMPTY_RETURN" value="false"/>
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="0"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="EXTENDS_LIST_WRAP" value="1"/>
<option name="THROWS_KEYWORD_WRAP" value="1"/>
<option name="METHOD_CALL_CHAIN_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="WRAP_COMMENTS" value="true"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
</code_scheme>

View File

@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>pn532</groupId>
<project
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>pn532-sdk</artifactId>
<version>1.0.2</version>
<description>POM was created from install:install-file</description>
<groupId>pn532</groupId>
<modelVersion>4.0.0</modelVersion>
<version>1.0.2</version>
</project>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>pn532</groupId>
<artifactId>pn532-sdk</artifactId>
<groupId>pn532</groupId>
<versioning>
<lastUpdated>20231116111447</lastUpdated>
<release>1.0.2</release>
<versions>
<version>1.0.2</version>
</versions>
<lastUpdated>20231116111447</lastUpdated>
</versioning>
</metadata>

312
pom.xml
View File

@@ -1,165 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>schafkopf-backend-java</artifactId>
<groupId>org.example</groupId>
<artifactId>schafkopf-backend-java</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<finalName>schafkopf-backend-build</finalName>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- DEPENDENCIES VERSIONS -->
<slf4j.version>1.7.32</slf4j.version>
<pi4j.version>2.4.0</pi4j.version>
<maven-compiler.version>3.5.1</maven-compiler.version>
<plugins>
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<configuration>
<configLocation>google_checks.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failOnViolation>true</failOnViolation>
<violationSeverity>warning</violationSeverity>
</configuration>
<goals>
<goal>check</goal>
</goals>
<id>validate</id>
<phase>validate</phase>
</execution>
</executions>
<groupId>org.apache.maven.plugins</groupId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.schafkopf.BackendServer</mainClass>
</manifest>
</archive>
</configuration>
<version>3.3.0</version>
</plugin>
</properties>
<build>
<finalName>schafkopf-backend-build</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<configLocation>google_checks.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failOnViolation>true</failOnViolation>
<violationSeverity>warning</violationSeverity>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>org.example.BackendServer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<verbose>false</verbose>
</configuration>
<version>3.11.0</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<verbose>false</verbose>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<groupId>org.apache.maven.plugins</groupId>
<version>3.5.1</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<artifactId>slf4j-simple</artifactId>
<groupId>org.slf4j</groupId>
<version>${slf4j.version}</version>
</dependency>
<!-- To write basic websockets against -->
<dependency>
<artifactId>websocket-jetty-api</artifactId>
<groupId>org.eclipse.jetty.websocket</groupId>
<version>11.0.15</version>
</dependency>
<!-- To run websockets in embedded server -->
<dependency>
<artifactId>websocket-jetty-server</artifactId>
<groupId>org.eclipse.jetty.websocket</groupId>
<version>11.0.15</version>
</dependency>
<dependency>
<artifactId>jetty-servlets</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>11.0.15</version>
</dependency>
<!-- To run websockets client -->
<dependency>
<artifactId>websocket-jetty-client</artifactId>
<groupId>org.eclipse.jetty.websocket</groupId>
<version>11.0.15</version>
</dependency>
<dependency>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
<version>2.10.1</version>
</dependency>
<dependency>
<artifactId>dotenv-java</artifactId>
<groupId>io.github.cdimascio</groupId>
<version>3.0.0</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>in-project</id>
<name>In Project Repo</name>
<url>file://${project.basedir}/lib</url>
</repository>
</repositories>
<!-- include Pi4J Core -->
<dependency>
<artifactId>pi4j-core</artifactId>
<groupId>com.pi4j</groupId>
<version>${pi4j.version}</version> <!-- Use the latest version available -->
</dependency>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- To write basic websockets against -->
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-api</artifactId>
<version>11.0.15</version>
</dependency>
<!-- To run websockets in embedded server -->
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-server</artifactId>
<version>11.0.15</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>11.0.15</version>
</dependency>
<!-- To run websockets client -->
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-client</artifactId>
<version>11.0.15</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>dotenv-java</artifactId>
<version>3.0.0</version>
</dependency>
<!-- include Pi4J Core -->
<dependency>
<groupId>com.pi4j</groupId>
<artifactId>pi4j-core</artifactId>
<version>${pi4j.version}</version> <!-- Use the latest version available -->
</dependency>
<!-- include Pi4J Plugins (Platforms and I/O Providers) -->
<dependency>
<groupId>com.pi4j</groupId>
<artifactId>pi4j-plugin-raspberrypi</artifactId>
<version>${pi4j.version}</version>
</dependency>
<dependency>
<groupId>com.pi4j</groupId>
<artifactId>pi4j-plugin-pigpio</artifactId>
<version>${pi4j.version}</version>
</dependency>
<!-- include Pi4J Plugins (Platforms and I/O Providers) -->
<dependency>
<artifactId>pi4j-plugin-raspberrypi</artifactId>
<groupId>com.pi4j</groupId>
<version>${pi4j.version}</version>
</dependency>
<dependency>
<artifactId>pi4j-plugin-pigpio</artifactId>
<groupId>com.pi4j</groupId>
<version>${pi4j.version}</version>
</dependency>
<dependency>
<groupId>pn532</groupId>
<artifactId>pn532-sdk</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<dependency>
<artifactId>pn532-sdk</artifactId>
<groupId>pn532</groupId>
<version>1.0.2</version>
</dependency>
</dependencies>
<groupId>org.example</groupId>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven-compiler.version>3.5.1</maven-compiler.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<!-- DEPENDENCIES VERSIONS -->
<pi4j.version>2.4.0</pi4j.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>1.7.32</slf4j.version>
</properties>
<repositories>
<repository>
<id>in-project</id>
<name>In Project Repo</name>
<url>file://${project.basedir}/lib</url>
</repository>
</repositories>
<version>1.0-SNAPSHOT</version>
</project>

View File

@@ -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<FrontendEndpoint> 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<DispatcherType> 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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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<I2C> 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();
}
}
}
}
}

View File

@@ -1,165 +0,0 @@
package org.example;
import java.util.ArrayList;
import java.util.List;
public class KartenUtil {
public static List<Karte> getKartenByFarbe(List<Karte> karten, String farbe) {
List<Karte> result = new ArrayList<>();
for (Karte karte : karten) {
if (karte.getFarbe().equalsIgnoreCase(farbe)) {
result.add(karte);
}
}
return result;
}
public static List<Karte> getKartenBySymbol(List<Karte> karten, String symbol) {
List<Karte> result = new ArrayList<>();
for (Karte karte : karten) {
if (karte.getSymbol().equalsIgnoreCase(symbol)) {
result.add(karte);
}
}
return result;
}
public static List<Karte> 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<Karte> 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<Karte> kartenList = initializeSchafKopfCardDeck();
for (Karte karte : kartenList) {
if (karte.getId().equalsIgnoreCase(id)) {
return karte;
}
}
return null;
}
public static void removeCards(List<Karte> allCards, List<Karte> cardsToRemove) {
allCards.removeAll(cardsToRemove);
}
}

View File

@@ -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");
}
}
}

View File

@@ -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<Karte> kartenList = KartenUtil.initializeSchafKopfCardDeck();
List<Karte> oberKarten = KartenUtil.getKartenBySymbol(kartenList, "o");
List<Karte> 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<Karte> kartenList = KartenUtil.initializeSchafKopfCardDeck();
List<Karte> oberKarten = KartenUtil.getKartenBySymbol(kartenList, "o");
kartenList.removeAll(oberKarten);
this.trumpfKarten = new ArrayList<>(oberKarten);
this.farbKarten = new ArrayList<>(kartenList);
}
}

View File

@@ -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<Karte> kartenList = KartenUtil.initializeSchafKopfCardDeck();
List<Karte> 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);
}
}

View File

@@ -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<Karte> kartenList = KartenUtil.initializeSchafKopfCardDeck();
List<Karte> unterKarten = KartenUtil.getKartenBySymbol(kartenList, "u");
List<Karte> 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);
}
}

View File

@@ -1,20 +0,0 @@
package org.example.spielController;
import org.example.Karte;
import java.util.List;
public abstract class SpielController {
protected List<Karte> trumpfKarten;
protected List<Karte> farbKarten;
public List<Karte> getTrumpfKarten() {
return trumpfKarten;
}
public List<Karte> getFarbKarten() {
return farbKarten;
}
}

View File

@@ -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<Karte> kartenList = KartenUtil.initializeSchafKopfCardDeck();
List<Karte> unterKarten = KartenUtil.getKartenBySymbol(kartenList, "u");
List<Karte> 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<Karte> kartenList = KartenUtil.initializeSchafKopfCardDeck();
List<Karte> unterKarten = KartenUtil.getKartenBySymbol(kartenList, "u");
kartenList.removeAll(unterKarten);
this.trumpfKarten = new ArrayList<>(unterKarten);
this.farbKarten = new ArrayList<>(kartenList);
}
}

View File

@@ -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<FrontendEndpoint> 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<DispatcherType> 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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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<I2C> 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();
}
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<Karte> kartenListe;
public KartenListe() {
this.kartenListe = new ArrayList<>();
}
public KartenListe(KartenListe liste) {
this.kartenListe = new ArrayList<>(liste.getKartenListe());
}
public List<Karte> 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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
};
}
}

View File

@@ -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");
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}