Mono Repo
* moveBackend * added Frontend * added env support for COM port * added frontend into monorepo
2
Backend/.env
Normal file
@@ -0,0 +1,2 @@
|
||||
VITE_APP_WEBSOCKET_IP=localhost
|
||||
COM_PORT=COM3
|
||||
40
Backend/.gitignore
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
/.idea/
|
||||
.env
|
||||
1
Backend/SpielController.drawio
Normal file
598
Backend/intellij-java-google-style.xml
Normal 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>
|
||||
BIN
Backend/lib/pn532/pn532-sdk/1.0.2/pn532-sdk-1.0.2.jar
Normal file
@@ -0,0 +1 @@
|
||||
171ab3333078fd908c878b85563a5ccc
|
||||
@@ -0,0 +1 @@
|
||||
2bf9f8b279977cb5511cb075f4f2cd316e2bfa62
|
||||
11
Backend/lib/pn532/pn532-sdk/1.0.2/pn532-sdk-1.0.2.pom
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<description>POM was created from install:install-file</description>
|
||||
<groupId>pn532</groupId>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>1.0.2</version>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
c0332fdac981cf53dc426b4fb6a173df
|
||||
@@ -0,0 +1 @@
|
||||
d6d7adcafc0119db3ec26d1bf8522fff1e78160c
|
||||
12
Backend/lib/pn532/pn532-sdk/maven-metadata-local.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<artifactId>pn532-sdk</artifactId>
|
||||
<groupId>pn532</groupId>
|
||||
<versioning>
|
||||
<lastUpdated>20231116111447</lastUpdated>
|
||||
<release>1.0.2</release>
|
||||
<versions>
|
||||
<version>1.0.2</version>
|
||||
</versions>
|
||||
</versioning>
|
||||
</metadata>
|
||||
1
Backend/lib/pn532/pn532-sdk/maven-metadata-local.xml.md5
Normal file
@@ -0,0 +1 @@
|
||||
324d2ea359305a5cdef2fd48169e4c6d
|
||||
@@ -0,0 +1 @@
|
||||
68b60db960171920acbf8b33283396ded102e64e
|
||||
187
Backend/pom.xml
Normal file
@@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
|
||||
<build>
|
||||
<finalName>schafkopf-backend-build</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<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>
|
||||
|
||||
<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-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>
|
||||
<groupId>com.fazecast</groupId>
|
||||
<artifactId>jSerialComm</artifactId>
|
||||
<version>2.6.0</version> <!-- Check for the latest version on the official repository -->
|
||||
</dependency>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- include Pi4J Core -->
|
||||
<dependency>
|
||||
<artifactId>pi4j-core</artifactId>
|
||||
<groupId>com.pi4j</groupId>
|
||||
<version>${pi4j.version}</version> <!-- Use the latest version available -->
|
||||
</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>
|
||||
<artifactId>pn532-sdk</artifactId>
|
||||
<groupId>pn532</groupId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-web</artifactId>
|
||||
<version>17</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>
|
||||
255
Backend/src/main/java/org/schafkopf/BackendServer.java
Normal file
@@ -0,0 +1,255 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import javafx.application.Application;
|
||||
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;
|
||||
import org.schafkopf.cardreader.CardReader;
|
||||
import org.schafkopf.cardreader.GpioReader;
|
||||
import org.schafkopf.cardreader.UsbCardReader;
|
||||
|
||||
/** Main Class that represents the Backend Server. */
|
||||
public class BackendServer {
|
||||
private final Server server;
|
||||
private final ServerConnector connector;
|
||||
private CountDownLatch nfcLatch = new CountDownLatch(1);
|
||||
private Boolean readingMode = false;
|
||||
private String uidString = "";
|
||||
|
||||
/** Important variables. */
|
||||
public final Schafkopf schafkopfGame;
|
||||
|
||||
private final CardReader nfcLeser;
|
||||
private final List<FrontendEndpoint> frontendEndpoints = new ArrayList<>();
|
||||
|
||||
/** 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);
|
||||
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
if (osName.contains("win")) {
|
||||
// Windows
|
||||
nfcLeser = new UsbCardReader(this);
|
||||
} else if (osName.contains("nix") || osName.contains("nux") || osName.contains("mac")) {
|
||||
// Unix/Linux/Mac
|
||||
// You can add additional checks for specific Linux distributions or macOS versions if needed
|
||||
// For now, assuming Raspberry Pi is running Linux
|
||||
nfcLeser = new GpioReader(this);
|
||||
} else {
|
||||
// Other OS
|
||||
throw new RuntimeException("Unsupported OS: " + osName);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
URL webContentUrl = getClass().getClassLoader().getResource("web-content");
|
||||
if (webContentUrl == null) {
|
||||
throw new RuntimeException("Unable to find 'web-content' directory");
|
||||
}
|
||||
|
||||
String webContentPath = webContentUrl.toExternalForm();
|
||||
context.setResourceBase(webContentPath);
|
||||
|
||||
System.out.println("Web Content Path: " + webContentPath);
|
||||
|
||||
// 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));
|
||||
});
|
||||
|
||||
// Integrate simple HTTP server
|
||||
startHttpServer();
|
||||
new Thread(this::launchJavaFx).start();
|
||||
}
|
||||
|
||||
private void launchJavaFx() {
|
||||
Application.launch(JavaFxApp.class);
|
||||
}
|
||||
|
||||
private void startHttpServer() {
|
||||
try {
|
||||
HttpServer httpServer = HttpServer.create(new InetSocketAddress(8081), 0);
|
||||
httpServer.createContext("/", new MyHandler());
|
||||
httpServer.setExecutor(null);
|
||||
httpServer.start();
|
||||
System.out.println("HTTP Server started on port 8081");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static class MyHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange t) throws IOException {
|
||||
String path = t.getRequestURI().getPath();
|
||||
if ("/".equals(path)) {
|
||||
path = "/index.html"; // default to index.html
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream fileStream =
|
||||
getClass().getClassLoader().getResourceAsStream("web-content" + path);
|
||||
if (fileStream != null) {
|
||||
byte[] data = fileStream.readAllBytes();
|
||||
// Set the appropriate MIME type for JavaScript files
|
||||
String mimeType = getMimeType(path);
|
||||
t.getResponseHeaders().set("Content-Type", mimeType);
|
||||
t.sendResponseHeaders(200, data.length);
|
||||
|
||||
try (OutputStream os = t.getResponseBody()) {
|
||||
os.write(data);
|
||||
}
|
||||
} else {
|
||||
// File not found
|
||||
t.sendResponseHeaders(404, -1);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
t.sendResponseHeaders(500, -1);
|
||||
}
|
||||
}
|
||||
|
||||
private String getMimeType(String path) {
|
||||
if (path.endsWith(".js")) {
|
||||
return "application/javascript";
|
||||
} else if (path.endsWith(".html")) {
|
||||
return "text/html";
|
||||
} else if (path.endsWith(".css")) {
|
||||
return "text/css";
|
||||
}
|
||||
// Add more MIME types as needed
|
||||
return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
|
||||
/** 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);
|
||||
}
|
||||
|
||||
private void setPort(int port) {
|
||||
connector.setPort(port);
|
||||
}
|
||||
|
||||
private void start() throws Exception {
|
||||
server.start();
|
||||
}
|
||||
|
||||
private 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());
|
||||
}
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
77
Backend/src/main/java/org/schafkopf/FrontendEndpoint.java
Normal 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.schafkopfGame.startGame();
|
||||
}
|
||||
|
||||
if (message.contains("stopsimulation")) {
|
||||
backendServer.schafkopfGame.stopGame();
|
||||
}
|
||||
|
||||
if (message.contains("showtrumpf")) {
|
||||
backendServer.schafkopfGame.showTrumpf();
|
||||
}
|
||||
|
||||
if (message.contains("showfarben")) {
|
||||
backendServer.schafkopfGame.showFarbe();
|
||||
}
|
||||
|
||||
if (message.contains("setgame")) {
|
||||
backendServer.schafkopfGame.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
80
Backend/src/main/java/org/schafkopf/GameState.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenFarbe;
|
||||
|
||||
/** GameState. */
|
||||
public class GameState {
|
||||
|
||||
public GamePhase getGamePhase() {
|
||||
return this.gamePhase;
|
||||
}
|
||||
|
||||
/** GamePhase. */
|
||||
public enum GamePhase {
|
||||
CHOOSE_GAME("Spiel muss gewählt werden"),
|
||||
|
||||
GAME_START("Warten auf das Legen einer Karte"),
|
||||
|
||||
TRICK_START("Warten auf das Legen einer Karte"),
|
||||
WAIT_FOR_CARD("Warten auf das Legen einer Karte"),
|
||||
PLAYER_CARD("Warten auf das Legen einer Karte"),
|
||||
PLAYER_TRICK("Spieler sticht"),
|
||||
GAME_STOP("Spieler sticht");
|
||||
// Add more phases as needed
|
||||
|
||||
private final String description;
|
||||
|
||||
GamePhase(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
private GamePhase gamePhase;
|
||||
private Integer currentPlayer; // Using Integer to allow for null
|
||||
private Karte card;
|
||||
private KartenFarbe color;
|
||||
private boolean trumpf;
|
||||
|
||||
// Constructors, getters, and setters
|
||||
|
||||
public GameState(GamePhase phase) {
|
||||
this.gamePhase = phase;
|
||||
}
|
||||
|
||||
public GameState(GamePhase phase, Integer player) {
|
||||
this.gamePhase = phase;
|
||||
this.currentPlayer = player;
|
||||
}
|
||||
|
||||
/** GameState. */
|
||||
public GameState(GamePhase phase, Integer player, Karte card, KartenFarbe color, boolean trumpf) {
|
||||
this.gamePhase = phase;
|
||||
this.currentPlayer = player;
|
||||
this.card = card;
|
||||
this.color = color;
|
||||
this.trumpf = trumpf;
|
||||
}
|
||||
|
||||
/** GameState. */
|
||||
public GameState(GamePhase phase, Integer player, Karte card) {
|
||||
this.gamePhase = phase;
|
||||
this.currentPlayer = player;
|
||||
this.card = card;
|
||||
}
|
||||
|
||||
/** GameState. */
|
||||
public JsonObject getJson() {
|
||||
Gson gson = new Gson();
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.add("gamestate", gson.toJsonTree(this));
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
50
Backend/src/main/java/org/schafkopf/JavaFxApp.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.web.WebView;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/** Frontend Window. */
|
||||
public class JavaFxApp extends Application {
|
||||
|
||||
private static final String FRONTEND_URL =
|
||||
"http://localhost:8081"; // Replace with your frontend URL
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
// Create a WebView
|
||||
WebView webView = new WebView();
|
||||
|
||||
// Load the frontend URL
|
||||
webView.getEngine().load(FRONTEND_URL);
|
||||
|
||||
// Create a Scene with the WebView
|
||||
Scene scene = new Scene(webView, 800, 600);
|
||||
|
||||
// Set up the Stage
|
||||
primaryStage.setTitle("Schafkopfen");
|
||||
primaryStage.setScene(scene);
|
||||
|
||||
primaryStage.setFullScreenExitHint("");
|
||||
|
||||
// Set the stage to fullscreen
|
||||
primaryStage.setFullScreen(true);
|
||||
|
||||
// Add event handler for the Escape key to toggle fullscreen
|
||||
scene.setOnKeyPressed(
|
||||
event -> {
|
||||
if (event.getCode() == KeyCode.F11) {
|
||||
primaryStage.setFullScreen(!primaryStage.isFullScreen());
|
||||
}
|
||||
});
|
||||
|
||||
// Show the Stage
|
||||
primaryStage.show();
|
||||
}
|
||||
}
|
||||
193
Backend/src/main/java/org/schafkopf/Schafkopf.java
Normal file
@@ -0,0 +1,193 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import org.schafkopf.GameState.GamePhase;
|
||||
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 GameState gameState = new GameState(GamePhase.GAME_STOP);
|
||||
private Thread spielThread;
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
|
||||
public Player[] getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/** 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();
|
||||
}
|
||||
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.getGamePhase() != GamePhase.GAME_STOP) {
|
||||
System.out.println("Game already started!");
|
||||
server.sendMessageToAllFrontendEndpoints("Game already started!");
|
||||
} else {
|
||||
gameState = new GameState(GamePhase.GAME_START);
|
||||
setAndSendGameState(gameState);
|
||||
System.out.println("Start Game");
|
||||
|
||||
// KartenListe botHand = KartenUtil.zieheZufallsHand(8);
|
||||
KartenListe botHand = new KartenListe();
|
||||
botHand.addKarten(Karte.EICHEL_7);
|
||||
botHand.addKarten(Karte.SCHELL_7);
|
||||
botHand.addKarten(Karte.BLATT_7);
|
||||
|
||||
botHand.addKarten(Karte.EICHEL_X);
|
||||
botHand.addKarten(Karte.HERZ_X);
|
||||
botHand.addKarten(Karte.HERZ_7);
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
spielThread = new Thread(() -> new Spielablauf(this, spiel));
|
||||
|
||||
spielThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set GameState to "stopped" and interrupt Game Thread. */
|
||||
public void stopGame() {
|
||||
if (gameState.getGamePhase() == GamePhase.GAME_STOP) {
|
||||
System.out.println("no active Game!");
|
||||
server.sendMessageToAllFrontendEndpoints("no active Game!");
|
||||
} else {
|
||||
gameState = new GameState(GamePhase.GAME_STOP);
|
||||
setAndSendGameState(gameState);
|
||||
}
|
||||
|
||||
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 void setAndSendGameState(GameState gameState) {
|
||||
this.gameState = gameState;
|
||||
this.server.sendMessageToAllFrontendEndpoints(this.gameState.getJson());
|
||||
}
|
||||
|
||||
public GameState getGameState() {
|
||||
return this.gameState;
|
||||
}
|
||||
}
|
||||
86
Backend/src/main/java/org/schafkopf/Spielablauf.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import org.schafkopf.GameState.GamePhase;
|
||||
import org.schafkopf.karte.Karte;
|
||||
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 = new KartenListe();
|
||||
|
||||
private final KartenListe tischKarten = new KartenListe();
|
||||
|
||||
private final SpielController spiel;
|
||||
|
||||
private final Player[] players;
|
||||
|
||||
private final Schafkopf schafkopf;
|
||||
|
||||
Spielablauf(Schafkopf schafkopf, SpielController spiel) {
|
||||
this.schafkopf = schafkopf;
|
||||
this.spiel = spiel;
|
||||
this.players = schafkopf.getPlayer();
|
||||
|
||||
playRound();
|
||||
}
|
||||
|
||||
private void playRound() {
|
||||
int startingPlayer = 0;
|
||||
|
||||
logger.info("Starte Stiche");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
logger.info("Stich: {}", i);
|
||||
startingPlayer = playTrick(startingPlayer);
|
||||
}
|
||||
schafkopf.stopGame();
|
||||
}
|
||||
|
||||
private int playTrick(int startingPlayer) {
|
||||
schafkopf.setAndSendGameState(new GameState(GamePhase.TRICK_START));
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int currentPlayer = (i + startingPlayer) % 4;
|
||||
|
||||
logger.info("Spieler ist dran: {}", currentPlayer);
|
||||
schafkopf.setAndSendGameState(new GameState(GamePhase.WAIT_FOR_CARD, currentPlayer));
|
||||
|
||||
Karte playedCard = players[currentPlayer].play(spiel, tischKarten, gespielteKarten);
|
||||
tischKarten.addKarten(playedCard);
|
||||
|
||||
schafkopf.setAndSendGameState(
|
||||
new GameState(
|
||||
GamePhase.PLAYER_CARD,
|
||||
currentPlayer,
|
||||
playedCard,
|
||||
tischKarten.getByIndex(0).getFarbe(),
|
||||
spiel.isTrumpf(tischKarten.getByIndex(0))));
|
||||
}
|
||||
int stichSpieler = SpielController.welcheKarteSticht(tischKarten);
|
||||
|
||||
logger.info("Stiche ende");
|
||||
|
||||
int winningPlayerIndex = (startingPlayer + stichSpieler) % 4;
|
||||
logger.warn("Karte sticht: {}", winningPlayerIndex);
|
||||
|
||||
schafkopf.setAndSendGameState(
|
||||
new GameState(
|
||||
GamePhase.PLAYER_TRICK, winningPlayerIndex, tischKarten.getByIndex(stichSpieler)));
|
||||
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("error sleep");
|
||||
}
|
||||
|
||||
gespielteKarten.addKarten(tischKarten);
|
||||
tischKarten.clear();
|
||||
|
||||
return winningPlayerIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.schafkopf.cardreader;
|
||||
|
||||
import org.schafkopf.BackendServer;
|
||||
|
||||
/** Class that represents one Card Reader. */
|
||||
public abstract class CardReader {
|
||||
|
||||
protected static BackendServer server;
|
||||
|
||||
public CardReader(BackendServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.schafkopf.cardreader;
|
||||
|
||||
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;
|
||||
import org.schafkopf.BackendServer;
|
||||
|
||||
/** Class that represents the NFC Reader. */
|
||||
public final class GpioReader extends CardReader {
|
||||
|
||||
/**
|
||||
* Creates an Instance of the KartenLeser.
|
||||
*
|
||||
* @param server Backend Server to call methods on.
|
||||
*/
|
||||
public GpioReader(BackendServer server) {
|
||||
super(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.schafkopf.cardreader;
|
||||
|
||||
import com.fazecast.jSerialComm.SerialPort;
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import org.schafkopf.BackendServer;
|
||||
|
||||
/** Class that represents the NFC Reader. */
|
||||
public class UsbCardReader extends CardReader {
|
||||
|
||||
private volatile boolean isRunning = true;
|
||||
Dotenv dotenv = Dotenv.configure().directory("./").load();
|
||||
private String PORT_NAME = dotenv.get("COM_PORT");
|
||||
|
||||
/**
|
||||
* Creates an Instance of the KartenLeser.
|
||||
*
|
||||
* @param server Backend Server to call methods on.
|
||||
*/
|
||||
public UsbCardReader(BackendServer server) {
|
||||
super(server);
|
||||
|
||||
new Thread(this::run).start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
/** run the reader. */
|
||||
public void run() {
|
||||
SerialPort[] ports = SerialPort.getCommPorts();
|
||||
SerialPort selectedPort = null;
|
||||
|
||||
for (SerialPort port : ports) {
|
||||
if (port.getSystemPortName().equals(this.PORT_NAME)) {
|
||||
selectedPort = port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedPort == null) {
|
||||
System.out.println(this.PORT_NAME + " not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ports.length == 0) {
|
||||
System.out.println("No serial ports found");
|
||||
return;
|
||||
}
|
||||
|
||||
SerialPort serialPort = selectedPort; // You may need to adjust this based on your setup
|
||||
serialPort.setBaudRate(115200);
|
||||
|
||||
if (serialPort.openPort()) {
|
||||
System.out.println("Serial port opened successfully");
|
||||
|
||||
try {
|
||||
while (isRunning) {
|
||||
if (serialPort.bytesAvailable() > 0) {
|
||||
byte[] buffer = new byte[serialPort.bytesAvailable()];
|
||||
int bytesRead = serialPort.readBytes(buffer, buffer.length);
|
||||
|
||||
String data = new String(buffer, 0, bytesRead, "UTF-8").trim();
|
||||
server.nfcGelesen(data);
|
||||
}
|
||||
|
||||
// Optional: Add a delay to avoid consuming too much CPU
|
||||
Thread.sleep(100);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
serialPort.closePort();
|
||||
System.out.println("Serial port closed");
|
||||
}
|
||||
} else {
|
||||
System.out.println("Failed to open serial port");
|
||||
}
|
||||
}
|
||||
}
|
||||
87
Backend/src/main/java/org/schafkopf/karte/Karte.java
Normal file
@@ -0,0 +1,87 @@
|
||||
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 {
|
||||
SCHELL_7(KartenFarbe.SCHELL, KartenSymbol.SEVEN),
|
||||
SCHELL_8(KartenFarbe.SCHELL, KartenSymbol.EIGHT),
|
||||
SCHELL_9(KartenFarbe.SCHELL, KartenSymbol.NINE),
|
||||
SCHELL_U(KartenFarbe.SCHELL, KartenSymbol.UNTER),
|
||||
SCHELL_O(KartenFarbe.SCHELL, KartenSymbol.OBER),
|
||||
SCHELL_K(KartenFarbe.SCHELL, KartenSymbol.KOENIG),
|
||||
SCHELL_X(KartenFarbe.SCHELL, KartenSymbol.TEN),
|
||||
SCHELL_A(KartenFarbe.SCHELL, KartenSymbol.ASS),
|
||||
HERZ_7(KartenFarbe.HERZ, KartenSymbol.SEVEN),
|
||||
HERZ_8(KartenFarbe.HERZ, KartenSymbol.EIGHT),
|
||||
HERZ_9(KartenFarbe.HERZ, KartenSymbol.NINE),
|
||||
HERZ_U(KartenFarbe.HERZ, KartenSymbol.UNTER),
|
||||
HERZ_O(KartenFarbe.HERZ, KartenSymbol.OBER),
|
||||
HERZ_K(KartenFarbe.HERZ, KartenSymbol.KOENIG),
|
||||
HERZ_X(KartenFarbe.HERZ, KartenSymbol.TEN),
|
||||
HERZ_A(KartenFarbe.HERZ, KartenSymbol.ASS),
|
||||
|
||||
BLATT_7(KartenFarbe.BLATT, KartenSymbol.SEVEN),
|
||||
BLATT_8(KartenFarbe.BLATT, KartenSymbol.EIGHT),
|
||||
BLATT_9(KartenFarbe.BLATT, KartenSymbol.NINE),
|
||||
BLATT_U(KartenFarbe.BLATT, KartenSymbol.UNTER),
|
||||
BLATT_O(KartenFarbe.BLATT, KartenSymbol.OBER),
|
||||
BLATT_K(KartenFarbe.BLATT, KartenSymbol.KOENIG),
|
||||
BLATT_X(KartenFarbe.BLATT, KartenSymbol.TEN),
|
||||
BLATT_A(KartenFarbe.BLATT, KartenSymbol.ASS),
|
||||
EICHEL_7(KartenFarbe.EICHEL, KartenSymbol.SEVEN),
|
||||
EICHEL_8(KartenFarbe.EICHEL, KartenSymbol.EIGHT),
|
||||
EICHEL_9(KartenFarbe.EICHEL, KartenSymbol.NINE),
|
||||
EICHEL_U(KartenFarbe.EICHEL, KartenSymbol.UNTER),
|
||||
EICHEL_O(KartenFarbe.EICHEL, KartenSymbol.OBER),
|
||||
EICHEL_K(KartenFarbe.EICHEL, KartenSymbol.KOENIG),
|
||||
EICHEL_X(KartenFarbe.EICHEL, KartenSymbol.TEN),
|
||||
EICHEL_A(KartenFarbe.EICHEL, KartenSymbol.ASS);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
21
Backend/src/main/java/org/schafkopf/karte/KartenFarbe.java
Normal 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;
|
||||
}
|
||||
}
|
||||
203
Backend/src/main/java/org/schafkopf/karte/KartenListe.java
Normal 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.
|
||||
*/
|
||||
public 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();
|
||||
}
|
||||
}
|
||||
38
Backend/src/main/java/org/schafkopf/karte/KartenSymbol.java
Normal 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;
|
||||
}
|
||||
}
|
||||
82
Backend/src/main/java/org/schafkopf/karte/KartenUtil.java
Normal 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 "04E7A9C2126F80" -> 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
43
Backend/src/main/java/org/schafkopf/player/BotPlayer.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package org.schafkopf.player;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.karte.KartenUtil;
|
||||
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, KartenListe gespielteKarten) {
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Karte card = spiel.welcheKarteSpielIch(true, gespielteKarten, eigeneKarten, tischKarten);
|
||||
|
||||
eigeneKarten.removeKarten(card);
|
||||
|
||||
System.out.println("Eigene Karte legen");
|
||||
return card;
|
||||
}
|
||||
|
||||
/** 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");
|
||||
}
|
||||
}
|
||||
23
Backend/src/main/java/org/schafkopf/player/LocalPlayer.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package org.schafkopf.player;
|
||||
|
||||
import org.schafkopf.Schafkopf;
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
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, KartenListe gespielteKarten) {
|
||||
return schafkopf.wartetAufKarte();
|
||||
}
|
||||
}
|
||||
11
Backend/src/main/java/org/schafkopf/player/Player.java
Normal file
@@ -0,0 +1,11 @@
|
||||
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, KartenListe gespielteKarten);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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 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 Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
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 Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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 Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
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 Karte welcheKarteSpielIch(boolean istSpieler, KartenListe gespielteKarten,
|
||||
KartenListe meineHand, KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
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;
|
||||
|
||||
/** Class that represents one Card of the game. */
|
||||
public SauSpielController(int activePlayer, KartenFarbe farbe) {
|
||||
super(activePlayer);
|
||||
this.suchFarbe = farbe;
|
||||
}
|
||||
|
||||
/** choose witch Card should be played with the right Game logic. */
|
||||
public Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
System.out.println("Ich spiele eine Karte Sauspiel");
|
||||
|
||||
int spielerNummer = tischKarten.size();
|
||||
|
||||
switch (spielerNummer) {
|
||||
case 0:
|
||||
if (istSpieler) {
|
||||
return meineHand.getLast();
|
||||
} else {
|
||||
return meineHand.getByIndex(0);
|
||||
}
|
||||
case 1:
|
||||
if (istSpieler) {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
|
||||
} else {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
|
||||
}
|
||||
case 2:
|
||||
if (istSpieler) {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
|
||||
} else {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
|
||||
}
|
||||
case 3:
|
||||
if (istSpieler) {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
|
||||
} else {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
|
||||
}
|
||||
default:
|
||||
System.out.println("Ungültige SpielerNummer");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
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 Karte welcheKarteSpielIch(
|
||||
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
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 ersteKarte color the Player has to play.
|
||||
* @param mode Mode the player chooses a Card if multiple are available.
|
||||
*/
|
||||
public static Karte farbeZugeben(KartenListe meineHand, Karte ersteKarte, int mode) {
|
||||
KartenListe hand = new KartenListe(meineHand);
|
||||
sortiereKarten(hand);
|
||||
|
||||
boolean trumpfGespielt = trumpfKarten.containsKarte(ersteKarte);
|
||||
|
||||
KartenListe handTrumpfKarten = hand.removeKarten(trumpfKarten);
|
||||
KartenListe handfarbKarten;
|
||||
|
||||
if (trumpfGespielt) {
|
||||
handfarbKarten = handTrumpfKarten;
|
||||
} else {
|
||||
handfarbKarten = hand.getKarten(ersteKarte.getFarbe());
|
||||
}
|
||||
|
||||
if (handfarbKarten.size() == 1) {
|
||||
return handfarbKarten.getByIndex(0);
|
||||
} else if (handfarbKarten.size() > 1) {
|
||||
return switch (mode) {
|
||||
case 0 -> // Abspatzen
|
||||
handfarbKarten.getByIndex(0);
|
||||
case 1, 2 -> // Stechen // Schmieren
|
||||
handfarbKarten.getLast();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
if (handfarbKarten.isEmpty()) {
|
||||
switch (mode) {
|
||||
case 0: // Abspatzen
|
||||
return hand.getByIndex(0);
|
||||
case 1: // Schmieren
|
||||
return hand.getLast();
|
||||
case 2: // Stechen
|
||||
if (!handTrumpfKarten.isEmpty()) {
|
||||
return handTrumpfKarten.getLast(); // trumpf reinspielen
|
||||
} else {
|
||||
return hand.getByIndex(0); // wenn kein Trumpf und farblos, abschpatzen
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten);
|
||||
|
||||
public KartenListe getTrumpfKarten() {
|
||||
return trumpfKarten;
|
||||
}
|
||||
|
||||
public boolean isTrumpf(Karte card) {
|
||||
return trumpfKarten.containsKarte(card);
|
||||
}
|
||||
|
||||
public KartenListe getFarbKarten() {
|
||||
return farbKarten;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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 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 Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
BIN
Backend/src/main/resources/web-content/assets/blatt_6.png
Normal file
|
After Width: | Height: | Size: 815 KiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_7.png
Normal file
|
After Width: | Height: | Size: 859 KiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_8.png
Normal file
|
After Width: | Height: | Size: 971 KiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_9.png
Normal file
|
After Width: | Height: | Size: 954 KiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_a.png
Normal file
|
After Width: | Height: | Size: 797 KiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_k.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_o.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_u.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
Backend/src/main/resources/web-content/assets/blatt_x.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
Backend/src/main/resources/web-content/assets/card_back.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_6.png
Normal file
|
After Width: | Height: | Size: 603 KiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_7.png
Normal file
|
After Width: | Height: | Size: 646 KiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_8.png
Normal file
|
After Width: | Height: | Size: 730 KiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_9.png
Normal file
|
After Width: | Height: | Size: 768 KiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_a.png
Normal file
|
After Width: | Height: | Size: 905 KiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_k.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_o.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_u.png
Normal file
|
After Width: | Height: | Size: 1008 KiB |
BIN
Backend/src/main/resources/web-content/assets/eichel_x.png
Normal file
|
After Width: | Height: | Size: 870 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_6.png
Normal file
|
After Width: | Height: | Size: 412 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_7.png
Normal file
|
After Width: | Height: | Size: 470 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_8.png
Normal file
|
After Width: | Height: | Size: 498 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_9.png
Normal file
|
After Width: | Height: | Size: 626 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_a.png
Normal file
|
After Width: | Height: | Size: 957 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_k.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
Backend/src/main/resources/web-content/assets/herz_o.png
Normal file
|
After Width: | Height: | Size: 1010 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_u.png
Normal file
|
After Width: | Height: | Size: 959 KiB |
BIN
Backend/src/main/resources/web-content/assets/herz_x.png
Normal file
|
After Width: | Height: | Size: 686 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_6.png
Normal file
|
After Width: | Height: | Size: 600 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_7.png
Normal file
|
After Width: | Height: | Size: 704 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_8.png
Normal file
|
After Width: | Height: | Size: 741 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_9.png
Normal file
|
After Width: | Height: | Size: 881 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_a.png
Normal file
|
After Width: | Height: | Size: 1009 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_k.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
Backend/src/main/resources/web-content/assets/schell_o.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
Backend/src/main/resources/web-content/assets/schell_u.png
Normal file
|
After Width: | Height: | Size: 1015 KiB |
BIN
Backend/src/main/resources/web-content/assets/schell_x.png
Normal file
|
After Width: | Height: | Size: 958 KiB |
1
Backend/src/main/resources/web-content/assets/vue.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 496 B |
15
Backend/src/main/resources/web-content/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue</title>
|
||||
<script type="module" crossorigin src="/assets/index-6278b98f.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-08f560d4.css">
|
||||
</head>
|
||||
<body class="bg-gray-800">
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||