From b583eedd7543338756dd5ce34df05a66b37be06e Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 4 Jun 2025 11:53:43 +0200 Subject: [PATCH 1/4] docs: add project documentation for Casino Gaming Platform --- docs/projektdokumentation.tex | 1351 +++++++++++++++++++++++++++++++++ 1 file changed, 1351 insertions(+) create mode 100644 docs/projektdokumentation.tex diff --git a/docs/projektdokumentation.tex b/docs/projektdokumentation.tex new file mode 100644 index 0000000..4d045f4 --- /dev/null +++ b/docs/projektdokumentation.tex @@ -0,0 +1,1351 @@ +\documentclass[12pt,a4paper]{report} +\usepackage[ngerman]{babel} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{geometry} +\usepackage{graphicx} +\usepackage{hyperref} +\usepackage{listings} +\usepackage{xcolor} +\usepackage{float} +\usepackage{caption} +\usepackage{subcaption} +\usepackage{longtable} +\usepackage{pifont} +\usepackage{booktabs} +\usepackage{fancyhdr} +\usepackage{tocloft} +\usepackage{dirtree} +\usepackage{enumitem} +\usepackage{tikz} +\usetikzlibrary{arrows.meta, positioning} + +% Seitenränder +\geometry{ + left=2.5cm, + right=2.5cm, + top=2.5cm, + bottom=2.5cm +} + +% Kopf- und Fußzeile +\pagestyle{fancy} +\fancyhf{} +\fancyhead[L]{\leftmark} +\fancyhead[R]{\thepage} +\renewcommand{\headrulewidth}{0.4pt} + +% Code-Highlighting +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codegray}{rgb}{0.5,0.5,0.5} +\definecolor{codepurple}{rgb}{0.58,0,0.82} +\definecolor{backcolour}{rgb}{0.95,0.95,0.92} + +\lstdefinestyle{mystyle}{ + backgroundcolor=\color{backcolour}, + commentstyle=\color{codegreen}, + keywordstyle=\color{magenta}, + numberstyle=\tiny\color{codegray}, + stringstyle=\color{codepurple}, + basicstyle=\ttfamily\footnotesize, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + numbers=left, + numbersep=5pt, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2 +} + +\lstset{style=mystyle} + +% Hyperref-Einstellungen +\hypersetup{ + colorlinks=true, + linkcolor=black, + filecolor=magenta, + urlcolor=blue, +} + +\begin{document} + +% Titelseite +\begin{titlepage} + \centering + \vspace*{2cm} + + {\Huge\bfseries Casino Gaming Platform\par} + \vspace{1.5cm} + {\Large\itshape Projektdokumentation für die IHK-Abschlussprüfung\par} + \vspace{2cm} + {\large\bfseries Fachinformatiker für Anwendungsentwicklung\par} + + \vfill + + {\large + \begin{tabular}{ll} + \textbf{Prüfling:} & [Name des Prüflings] \\ + \textbf{Prüflingsnummer:} & [Prüflingsnummer] \\ + \textbf{Ausbildungsbetrieb:} & Hitec GmbH \\ + \textbf{Projektbetreuer:} & [Betreuer] \\ + \textbf{Projektdauer:} & 70 Stunden \\ + \textbf{Abgabedatum:} & \today \\ + \end{tabular} + \par} + + \vfill +\end{titlepage} + +% Inhaltsverzeichnis +\pagenumbering{roman} +\tableofcontents +\cleardoublepage +\pagenumbering{arabic} + +% Hauptinhalt +\chapter{Beschreibung} + +\section{Umfeld} +Das Projekt wurde im Rahmen der Abschlussprüfung zum Fachinformatiker für Anwendungsentwicklung bei der Hitec GmbH entwickelt. + +\subsection{Produktportfolio der Hitec GmbH} +Die Hitec GmbH ist ein innovatives IT-Unternehmen, das sich auf die Entwicklung moderner Webanwendungen und digitaler Lösungen spezialisiert hat. Das Unternehmen deckt ein breites Spektrum an Technologien ab, von klassischen Enterprise-Anwendungen bis hin zu modernen Cloud-nativen Lösungen. + +\subsection{Weg zur Produktidee} +Die Casino Gaming Platform entstand als LF08 Projekt mit dem Ziel, eine vollständige Online-Casino-Plattform zu entwickeln. Die Produktidee basiert auf: + +\begin{itemize} + \item \textbf{Gamification-Trend:} Wachsende Nachfrage nach Online-Gaming-Plattformen + \item \textbf{Technologie-Demonstration:} Showcase moderner Full-Stack-Entwicklung (Angular 20 + Spring Boot 3.5) + \item \textbf{Bildungsziel:} Praktische Anwendung von Enterprise-Patterns und modernen Web-Technologien + \item \textbf{Marktforschung:} Integration aktueller Standards (OAuth2, Stripe, responsive Design) +\end{itemize} + +\section{Ziel} +Das Ziel dieses Projektes ist die Entwicklung eines Online-Casinos, welches verschiedene Spiele anbietet, um mit Echtgeld zu wetten. Dabei verzichten wir auf eine Auszahlungsmöglichkeit, um Einnahmen zu steigern und rechtliche Komplexitäten zu vermeiden. + +Die Plattform soll es Benutzern ermöglichen: +\begin{itemize} + \item Mit virtueller Währung verschiedene Casino-Spiele zu spielen + \item Sichere Einzahlungen über moderne Payment-Provider zu tätigen + \item Eine intuitive und responsive Benutzeroberfläche zu nutzen + \item Transparente Transaktionshistorien einzusehen +\end{itemize} + +\chapter{Vorbereitung} + +\section{Ist-Analyse} +Detaillierte Beschreibung des Problems oder der Marktlücke, welche unser Produkt lösen/füllen soll. + +\subsection{Identifizierte Marktlücken} +\begin{enumerate} + \item \textbf{Technische Komplexität:} Viele Casino-Plattformen nutzen veraltete Technologien + \item \textbf{Benutzerfreundlichkeit:} Schlechte mobile Erfahrung und komplexe Registrierung + \item \textbf{Sicherheitsstandards:} Mangelnde OAuth2-Integration und moderne Authentifizierung + \item \textbf{Payment-Integration:} Umständliche Einzahlungsprozesse ohne moderne Payment-APIs + \item \textbf{Transparenz:} Fehlende Nachvollziehbarkeit von Transaktionen und Spielverläufen +\end{enumerate} + +\section{Soll-Analyse} +\subsection{Spieleportfolio} +\begin{itemize} + \item Blackjack (mit Split/Double Down) + \item Slots mit konfigurierbarer RTP + \item Dice, Coinflip, Lootboxes + \item Geplant: Poker, Plinko +\end{itemize} + +\subsection{Benutzerverwaltung} +\begin{itemize} + \item Multi-Provider OAuth2 (GitHub, Google) + \item JWT-basierte Authentifizierung + \item E-Mail-Verifizierung und Passwort-Reset +\end{itemize} + +\subsection{Finanzsystem} +\begin{itemize} + \item Stripe-Integration für Einzahlungen + \item Virtuelle Währung mit Präzisions-Tracking (BigDecimal) + \item Transaktionshistorie mit Status-Tracking +\end{itemize} + +\subsection{Technische Anforderungen} +\begin{itemize} + \item Responsive Design (Mobile-First) + \item Real-time Updates ohne Page-Reload + \item Sichere API-Kommunikation +\end{itemize} + +\chapter{Durchführung} + +\section{Vorgehensweise} +Für die Projektdurchführung wurde Scrum als Vorgehensmodell gewählt. Dadurch wird am Anfang des Projektes und eines Sprints festgelegt, was gemacht werden soll, und jeder ist auf dem gleichen Wissensstand. Des Weiteren gibt es tägliche Updates vom Fortschritt, Probleme können schnell erkannt und angesprochen werden. Dazu kann man auch neue Anforderungen flexibel mit einbringen. + +\subsection{Verwendete Tools und Methoden} +\begin{itemize} + \item \textbf{Scrum:} Agile Projektmanagement-Methodik + \item \textbf{Jira:} Ticketing und Sprint-Planning + \item \textbf{Git:} Versionskontrolle mit Feature-Branch-Workflow + \item \textbf{CI/CD:} Automatisierte Build- und Deployment-Pipelines +\end{itemize} + +\section{Umsetzung} + +\subsection{Art der Datenhaltung} +PostgreSQL mit JPA/Hibernate ORM wurde als Datenbanklösung gewählt: +\begin{itemize} + \item \textbf{Verbindung:} JDBC mit Connection Pooling (HikariCP) + \item \textbf{Schema:} Domain-driven Design mit klarer Trennung + \item \textbf{Transaktionen:} @Transactional Boundaries für Konsistenz + \item \textbf{Migration:} Flyway für Datenbank-Versionierung +\end{itemize} + +\subsection{Klassenmodell} + +\subsubsection{Backend (Java)} +\dirtree{% +.1 Entity Layer. +.2 UserEntity. +.2 BlackJackGameEntity. +.2 TransactionEntity. +.2 LootBoxEntity. +.1 Repository Layer. +.2 Spring Data JPA. +.1 Service Layer. +.2 Business Logic. +.3 BlackJackService. +.3 BalanceService. +.3 DepositService. +.1 Controller Layer. +.2 REST APIs. +.1 Security Layer. +.2 JWT + OAuth2. +} + +\subsubsection{Frontend (TypeScript)} +\dirtree{% +.1 Models. +.2 User interfaces. +.2 Game interfaces. +.2 Transaction interfaces. +.1 Services. +.2 HTTP client wrappers. +.1 Components. +.2 Angular standalone components. +.1 Guards. +.2 Route protection. +} + +\subsection{Design Pattern} +\begin{enumerate} + \item \textbf{MVC Pattern:} Controller → Service → Repository + \item \textbf{Repository Pattern:} Datenzugriff-Abstraktion + \item \textbf{DTO Pattern:} API-Grenze mit Datenkapselung + \item \textbf{Strategy Pattern:} OAuth2-Provider (GitHub/Google) + \item \textbf{Observer Pattern:} Angular Signals für reaktive Updates +\end{enumerate} + +\subsection{Zusammenarbeit der einzelnen Module} + +\subsubsection{Backend-Architektur} +\begin{verbatim} +Security Layer ← JWT Filter ← Controllers ← Services ← Repositories ← Database + ↓ +OAuth2 Integration (GitHub/Google) + ↓ +Payment Integration (Stripe Webhooks) +\end{verbatim} + +\subsubsection{Frontend-Architektur} +\begin{verbatim} +Guards → Components → Services → HTTP Interceptors → Backend APIs + ↓ +Angular Router → Lazy Loading → Feature Modules +\end{verbatim} + +\subsection{Systemarchitektur} +Die Casino Gaming Platform basiert auf einer modernen Microservice-Architektur mit klarer Trennung zwischen Frontend und Backend. + +\subsubsection{Gesamtarchitektur} +\begin{tikzpicture}[ + box/.style={rectangle, draw, minimum width=3cm, minimum height=1.5cm, align=center}, + ->, >=Stealth, node distance=2cm and 1.5cm +] + +% Top row +\node[box] (angular) {Angular\\Frontend}; +\node[box, right=of angular] (spring) {Spring Boot\\Backend}; +\node[box, right=of spring] (postgres) {PostgreSQL\\Database}; + +% Bottom row +\node[box, below=of angular] (keycloak) {Keycloak\\Auth Server}; +\node[box, below=of spring] (stripe) {Stripe API\\Payment}; + +% Arrows top row +\draw (angular) -- (spring); +\draw (spring) -- (postgres); + +% Arrows to bottom row +\draw (angular.south) -- (keycloak.north); +\draw (spring.south) -- (stripe.north); + +\end{tikzpicture} + +\subsubsection{Backend-Paketstruktur} +Das Backend folgt dem Domain-Driven Design (DDD) Ansatz: + +\dirtree{% +.1 de.szut.casino. +.2 blackjack. +.3 BlackjackController.java. +.3 BlackjackService.java. +.3 BlackjackEntity.java. +.2 coinflip. +.3 CoinflipController.java. +.3 CoinflipService.java. +.2 config. +.3 SecurityConfig.java. +.3 DatabaseConfig.java. +.2 deposit. +.3 DepositController.java. +.3 StripeService.java. +.2 dice. +.3 DiceController.java. +.3 DiceService.java. +.2 exceptionHandling. +.3 GlobalExceptionHandler.java. +.2 health. +.3 HealthController.java. +.2 lootboxes. +.3 LootBoxEntity.java. +.3 RewardEntity.java. +.2 security. +.3 JwtAuthenticationConverter.java. +.2 shared. +.3 BaseEntity.java. +.3 AuditingConfig.java. +.2 slots. +.3 SlotsController.java. +.3 SlotsService.java. +.2 user. +.3 UserEntity.java. +.3 UserService.java. +} + +\subsubsection{Frontend-Modulstruktur} +Das Frontend ist modular aufgebaut mit Feature-Modulen: + +\dirtree{% +.1 app/feature/. +.2 auth. +.3 login. +.3 oauth2. +.3 recover-password. +.3 register. +.3 verify-email. +.2 deposit. +.3 deposit.component.ts. +.3 payment.service.ts. +.2 game. +.3 blackjack. +.4 components. +.5 animated-number. +.5 dealer-hand. +.5 game-controls. +.5 game-info. +.5 game-result. +.5 player-hand. +.5 playing-card. +.4 enum. +.4 models. +.4 services. +.3 coinflip. +.4 models. +.3 dice. +.3 slots. +.2 home. +.2 landing. +.2 lootboxes. +.3 lootbox-opening. +.3 lootbox-selection. +.3 services. +.2 transaction-history. +} + +\subsection{Funktionsweise des Blackjack-Algorithmus} +Als Beispiel für die Spiellogik wird hier der Blackjack-Algorithmus beschrieben: + +\begin{enumerate} + \item \textbf{Spielstart:} Dealer teilt je 2 Karten an Spieler und sich selbst aus + \item \textbf{Kartenwerte:} Ass = 1 oder 11, Bildkarten = 10, andere = Nennwert + \item \textbf{Spielerzug:} Hit (weitere Karte) oder Stand (beenden) + \item \textbf{Dealerzug:} Automatisch bis Kartenwert $\geq$ 17 + \item \textbf{Gewinnermittlung:} Nächster zu 21 gewinnt, bei Gleichstand Unentschieden +\end{enumerate} + +\section{Technologie-Stack} + +\subsection{Frontend-Technologien} +\begin{itemize} + \item \textbf{Angular 20}: Modernes TypeScript-basiertes Web-Framework + \item \textbf{TailwindCSS}: Utility-First CSS-Framework + \item \textbf{RxJS}: Reactive Extensions für asynchrone Programmierung + \item \textbf{Keycloak JS}: JavaScript-Adapter für Keycloak-Integration + \item \textbf{Stripe.js}: Sichere Payment-Integration +\end{itemize} + +\subsection{Backend-Technologien} +\begin{itemize} + \item \textbf{Spring Boot}: Java-basiertes Backend-Framework + \item \textbf{Spring Security}: Sicherheitsframework + \item \textbf{Spring Data JPA}: Datenbankzugriff + \item \textbf{PostgreSQL}: Relationale Datenbank + \item \textbf{Gradle}: Build-Management-Tool +\end{itemize} + +\subsection{Infrastructure \& Tools} +\begin{itemize} + \item \textbf{Docker}: Containerisierung + \item \textbf{Docker Compose}: Multi-Container-Orchestrierung + \item \textbf{Keycloak}: Identity und Access Management + \item \textbf{Mailpit}: E-Mail-Testing in der Entwicklung + \item \textbf{Swagger/OpenAPI}: API-Dokumentation +\end{itemize} + +\chapter{Implementierung} + +\section{Backend-Implementierung} + +\subsection{Spring Boot Konfiguration} +Die Hauptanwendungsklasse initialisiert die Spring Boot-Anwendung und konfiguriert grundlegende Beans: + +\begin{lstlisting}[language=Java, caption=CasinoApplication.java] +@SpringBootApplication +public class CasinoApplication { + public static void main(String[] args) { + SpringApplication.run(CasinoApplication.class, args); + } + + @Bean + public static RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Bean + public static JavaMailSenderImpl javaMailSenderImpl() { + return new JavaMailSenderImpl(); + } +} +\end{lstlisting} + +\subsection{Sicherheitskonfiguration} +Die Anwendung nutzt Keycloak für die Authentifizierung. Spring Security wird entsprechend konfiguriert: + +\begin{lstlisting}[language=Java, caption=Security Configuration] +@Configuration +@EnableWebSecurity +public class SecurityConfig { + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) { + return http + .authorizeHttpRequests(auth -> auth + .requestMatchers("/swagger/**").permitAll() + .requestMatchers("/health/**").permitAll() + .anyRequest().authenticated() + ) + .oauth2ResourceServer(oauth2 -> + oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter( + jwtAuthenticationConverter() + )) + ) + .build(); + } +} +\end{lstlisting} + +\subsection{Spieleimplementierung} +Jedes Spiel folgt einem einheitlichen Muster mit Controller, Service und Repository: + +\begin{lstlisting}[language=Java, caption=Beispiel: Blackjack Controller] +@RestController +@RequestMapping("/api/blackjack") +@RequiredArgsConstructor +public class BlackjackController { + private final BlackjackService blackjackService; + + @PostMapping("/start") + public ResponseEntity startGame() { + return ResponseEntity.ok( + blackjackService.startNewGame() + ); + } + + @PostMapping("/hit") + public ResponseEntity hit() { + return ResponseEntity.ok( + blackjackService.playerHit() + ); + } + + @PostMapping("/stand") + public ResponseEntity stand() { + return ResponseEntity.ok( + blackjackService.playerStand() + ); + } +} +\end{lstlisting} + +\section{Frontend-Implementierung} + +\subsection{Angular-Projektstruktur} +Das Frontend nutzt Angular's modulare Architektur mit Lazy Loading: + +\begin{lstlisting}[caption=App Routing Module] +const routes: Routes = [ + { + path: '', + loadChildren: () => import('./feature/landing/landing.module') + .then(m => m.LandingModule) + }, + { + path: 'games', + loadChildren: () => import('./feature/game/game.module') + .then(m => m.GameModule), + canActivate: [AuthGuard] + }, + { + path: 'deposit', + loadChildren: () => import('./feature/deposit/deposit.module') + .then(m => m.DepositModule), + canActivate: [AuthGuard] + } +]; +\end{lstlisting} + +\subsection{Komponenten-Implementierung} +Jede Spielkomponente folgt dem Angular-Standard mit TypeScript: + +\begin{lstlisting}[caption=Blackjack Component] +@Component({ + selector: 'app-blackjack', + templateUrl: './blackjack.component.html', + styleUrls: ['./blackjack.component.scss'] +}) +export class BlackjackComponent implements OnInit { + gameState$: Observable; + + constructor( + private blackjackService: BlackjackService, + private toastr: ToastrService + ) {} + + ngOnInit(): void { + this.gameState$ = this.blackjackService.getGameState(); + } + + startGame(): void { + this.blackjackService.startGame() + .subscribe({ + next: () => this.toastr.success('Spiel gestartet!'), + error: (err) => this.toastr.error('Fehler beim Starten') + }); + } +} +\end{lstlisting} + +\subsection{Service-Layer} +Services kapseln die Geschäftslogik und API-Kommunikation: + +\begin{lstlisting}[caption=Blackjack Service] +@Injectable({ + providedIn: 'root' +}) +export class BlackjackService { + private apiUrl = '/api/blackjack'; + private gameStateSubject = new BehaviorSubject(null); + + constructor(private http: HttpClient) {} + + startGame(): Observable { + return this.http.post(`${this.apiUrl}/start`, {}) + .pipe( + tap(state => this.gameStateSubject.next(state)), + catchError(this.handleError) + ); + } + + private handleError(error: HttpErrorResponse): Observable { + console.error('API Error:', error); + return throwError(() => error); + } +} +\end{lstlisting} + +\section{Datenbankdesign} + +\subsection{Entity-Relationship-Modell} +Die Datenbank verwendet folgende Hauptentitäten: + +\begin{lstlisting}[caption=Haupttabellen] +-- Benutzer-Tabelle +CREATE TABLE users ( + id UUID PRIMARY KEY, + keycloak_id VARCHAR(255) UNIQUE NOT NULL, + balance DECIMAL(19, 2) DEFAULT 0.00, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Transaktions-Tabelle +CREATE TABLE transactions ( + id UUID PRIMARY KEY, + user_id UUID REFERENCES users(id), + amount DECIMAL(19, 2) NOT NULL, + type VARCHAR(50) NOT NULL, + description TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Spielverlauf-Tabelle +CREATE TABLE game_history ( + id UUID PRIMARY KEY, + user_id UUID REFERENCES users(id), + game_type VARCHAR(50) NOT NULL, + bet_amount DECIMAL(19, 2), + win_amount DECIMAL(19, 2), + played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +\end{lstlisting} + +\subsection{JPA-Entitäten} +Die Datenbankentitäten werden als JPA-Entities modelliert: + +\begin{lstlisting}[caption=User Entity] +@Entity +@Table(name = "users") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserEntity { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + + @Column(unique = true, nullable = false) + private String keycloakId; + + @Column(precision = 19, scale = 2) + private BigDecimal balance = BigDecimal.ZERO; + + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List transactions; + + @CreationTimestamp + private LocalDateTime createdAt; + + @UpdateTimestamp + private LocalDateTime updatedAt; +} +\end{lstlisting} + +\chapter{Integration externer Dienste} + +\section{Keycloak-Integration} +Keycloak wird als zentraler Identity Provider verwendet: + +\subsection{Backend-Konfiguration} +\begin{lstlisting}[caption=application.yml] +spring: + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://localhost:8080/realms/casino + jwk-set-uri: http://localhost:8080/realms/casino/protocol/openid-connect/certs + +keycloak: + realm: casino + auth-server-url: http://localhost:8080 + ssl-required: external + resource: casino-backend + public-client: false + bearer-only: true +\end{lstlisting} + +\subsection{Frontend-Integration} +\begin{lstlisting}[caption=Keycloak Service] +@Injectable({ + providedIn: 'root' +}) +export class KeycloakService { + private keycloak: Keycloak; + + async init(): Promise { + this.keycloak = new Keycloak({ + url: 'http://localhost:8080', + realm: 'casino', + clientId: 'casino-frontend' + }); + + return await this.keycloak.init({ + onLoad: 'check-sso', + silentCheckSsoRedirectUri: + window.location.origin + '/assets/silent-check-sso.html' + }); + } +} +\end{lstlisting} + +\section{Stripe-Integration} +Stripe wird für sichere Zahlungsabwicklung verwendet: + +\subsection{Backend-Webhook} +\begin{lstlisting}[caption=Stripe Webhook Controller] +@RestController +@RequestMapping("/webhook") +public class StripeWebhookController { + @Value("${stripe.webhook.secret}") + private String webhookSecret; + + @PostMapping + public ResponseEntity handleWebhook( + @RequestBody String payload, + @RequestHeader("Stripe-Signature") String sigHeader + ) { + Event event = Webhook.constructEvent( + payload, sigHeader, webhookSecret + ); + + switch (event.getType()) { + case "payment_intent.succeeded": + handleSuccessfulPayment(event); + break; + case "payment_intent.payment_failed": + handleFailedPayment(event); + break; + } + + return ResponseEntity.ok("Received"); + } +} +\end{lstlisting} + +\subsection{Frontend-Integration} +\begin{lstlisting}[caption=Stripe Service] +@Injectable({ + providedIn: 'root' +}) +export class StripeService { + private stripe: Stripe; + + constructor() { + this.stripe = loadStripe(environment.stripePublicKey); + } + + async createPaymentIntent(amount: number): Observable { + return this.http.post('/api/deposits/create-intent', { + amount: amount * 100 // Cent-Betrag + }); + } +} +\end{lstlisting} + +\chapter{Qualitätssicherung} + +\section{CI/CD Setup} + +\subsection{Unit-Tests} +Jede Service-Klasse wird mit JUnit und Mockito getestet: + +\begin{lstlisting}[language=Java, caption=BlackjackService Test] +@ExtendWith(MockitoExtension.class) +class BlackjackServiceTest { + @Mock + private BlackjackRepository repository; + + @InjectMocks + private BlackjackService service; + + @Test + void testStartNewGame() { + // Given + when(repository.save(any())).thenReturn(new GameEntity()); + + // When + GameStateDto result = service.startNewGame(); + + // Then + assertNotNull(result); + assertEquals(2, result.getPlayerCards().size()); + assertEquals(2, result.getDealerCards().size()); + } +} +\end{lstlisting} + +\subsection{Integrationstests} +Spring Boot Test für API-Endpoints: + +\begin{lstlisting}[language=Java, caption=Integration Test] +@SpringBootTest +@AutoConfigureMockMvc +class BlackjackControllerIntegrationTest { + @Autowired + private MockMvc mockMvc; + + @Test + @WithMockUser + void testStartGameEndpoint() throws Exception { + mockMvc.perform(post("/api/blackjack/start") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.playerCards").isArray()) + .andExpect(jsonPath("$.dealerCards").isArray()); + } +} +\end{lstlisting} + +\section{Frontend-Tests} + +\subsection{Komponenten-Tests} +Angular-Komponenten werden mit Jasmine und Karma getestet: + +\begin{lstlisting}[caption=Component Test] +describe('BlackjackComponent', () => { + let component: BlackjackComponent; + let fixture: ComponentFixture; + let mockService: jasmine.SpyObj; + + beforeEach(() => { + const spy = jasmine.createSpyObj('BlackjackService', + ['startGame', 'getGameState']); + + TestBed.configureTestingModule({ + declarations: [BlackjackComponent], + providers: [ + { provide: BlackjackService, useValue: spy } + ] + }); + + fixture = TestBed.createComponent(BlackjackComponent); + component = fixture.componentInstance; + mockService = TestBed.inject(BlackjackService) as any; + }); + + it('should start a new game', () => { + mockService.startGame.and.returnValue(of(mockGameState)); + + component.startGame(); + + expect(mockService.startGame).toHaveBeenCalled(); + }); +}); +\end{lstlisting} + +\subsection{E2E-Tests} +End-to-End-Tests mit Cypress: + +\begin{lstlisting}[caption=E2E Test] +describe('Blackjack Game', () => { + beforeEach(() => { + cy.login('testuser', 'password'); + cy.visit('/games/blackjack'); + }); + + it('should play a complete game', () => { + cy.get('[data-cy=start-game]').click(); + cy.get('[data-cy=player-cards]').should('be.visible'); + cy.get('[data-cy=dealer-cards]').should('be.visible'); + + cy.get('[data-cy=hit-button]').click(); + cy.get('[data-cy=player-cards]') + .children().should('have.length.greaterThan', 2); + + cy.get('[data-cy=stand-button]').click(); + cy.get('[data-cy=game-result]').should('be.visible'); + }); +}); +\end{lstlisting} + +\chapter{Wirtschaftliche Betrachtung} + +\section{Marktuntersuchung} + +\subsection{Zielgruppe} +\textbf{Welche Zielgruppe soll angesprochen werden?} + +\begin{itemize} + \item \textbf{Primäre Zielgruppe:} Technik-affine Nutzer (18-35 Jahre) + \item \textbf{Sekundäre Zielgruppe:} Gelegenheitsspieler mit Fokus auf Benutzerfreundlichkeit +\end{itemize} + +\subsection{Erwartungen der Zielgruppe} +\textbf{Welche Erwartungen hat die Zielgruppe an das Produkt?} + +Die Zielgruppe erwartet ein unterhaltsames, fesselndes und optisch ansprechendes Spielerlebnis, das klassische Casino-Atmosphäre simuliert. Sie legt Wert auf: + +\begin{itemize} + \item Intuitive Benutzeroberfläche + \item Schnelle Ladezeiten + \item Abwechslungsreiche Spiele (Slots, Blackjack, CoinFlip etc.) + \item Transparente Transaktionshistorie + \item Mobile Optimierung + \item Sichere Zahlungsabwicklung +\end{itemize} + +\subsection{Marktvolumen und Marktpotential} +\textbf{Wie hoch ist bei der Zielgruppe das Marktvolumen und das Marktpotential?} + +Der Markt für Social Casinos und Online-Casinos mit Auszahlungsverweigerung ist weltweit wachsend. Laut Branchenanalysen (z.B. Statista, Business Research Insights) liegt das Volumen des globalen Social-Casino-Markts bei mehreren Milliarden USD pro Jahr, mit jährlichen Wachstumsraten im hohen einstelligen Prozentbereich. + +In Zielmärkten wie den USA, Europa und Teilen Asiens ist das Potenzial besonders hoch, insbesondere bei Nutzern, die Glücksspiel aus rechtlichen oder moralischen Gründen meiden, aber den Spielspaß schätzen. + +\subsection{Absatzpotential} +\textbf{Wie hoch ist bei der Zielgruppe das Absatzpotential?} + +Das Absatzpotential ist aufgrund des digitalen Charakters des Produkts nahezu unbegrenzt skalierbar. Wichtige Faktoren: + +\begin{itemize} + \item Keine physischen Produktionslimits + \item Globale Erreichbarkeit über das Internet + \item Virale Marketing-Effekte durch Social Gaming + \item Wiederkehrende Umsätze durch Einzahlungsmodell +\end{itemize} + +\subsection{Wettbewerbssituation} +\textbf{Wie stellt sich die Wettbewerbssituation dar?} + +Der Markt ist stark umkämpft mit etablierten Playern wie: +\begin{itemize} + \item PokerStars Casino + \item Slotomania + \item House of Fun + \item Big Fish Casino +\end{itemize} + +\textbf{Konkurrenzvorteile unserer Lösung:} +\begin{itemize} + \item Moderne Technologie-Stack (Angular + Spring Boot) + \item DSGVO-konforme Entwicklung von Grund auf + \item Keine Auszahlungen = höhere Gewinnmargen + \item Responsive Design für alle Endgeräte + \item Open-Source-Ansatz für Community-Entwicklung +\end{itemize} + +\subsection{Risiken} +\textbf{Wo liegen Risiken?} + +\begin{itemize} + \item \textbf{Rechtliche Risiken:} Sich ändernde Glücksspielgesetze + \item \textbf{Technische Risiken:} Skalierungsprobleme bei hohen Nutzerzahlen + \item \textbf{Marktrisiken:} Marktsättigung im Social Gaming Bereich + \item \textbf{Sicherheitsrisiken:} Hacking-Versuche und Betrug +\end{itemize} + +\section{Marketingmix / absatzpolitische Maßnahmen} + +\subsection{Preispolitik} +\textbf{Für welchen Preis wird das Produkt angeboten?} + +Das Produkt folgt einem Freemium-Modell: +\begin{itemize} + \item \textbf{Grundspiel:} Kostenlos mit Startguthaben + \item \textbf{Einzahlungen:} Gestaffelte Pakete (5€, 10€, 25€, 50€, 100€) + \item \textbf{Premium-Features:} Erweiterte Statistiken (2,99€/Monat) +\end{itemize} + +\subsection{Kommunikationspolitik} +\textbf{Wie und wo soll das Produkt beworben werden?} + +\begin{itemize} + \item \textbf{Social Media Marketing:} Instagram, TikTok, YouTube + \item \textbf{Influencer Marketing:} Gaming-Streamer und Content-Creator + \item \textbf{SEO/SEM:} Google Ads für relevante Suchbegriffe + \item \textbf{App Store Optimization:} Bei zukünftiger Mobile App +\end{itemize} + +\subsection{Distributionspolitik} +\textbf{Wie gelangt das Produkt zum Nutzer?} + +\begin{itemize} + \item \textbf{Web-Browser:} Direkter Zugang über casino-platform.com + \item \textbf{Progressive Web App:} Installation als App möglich + \item \textbf{Zukünftig:} Native Apps für iOS und Android +\end{itemize} + +\subsection{Wirtschaftlichkeitsbetrachtung} +\textbf{Wo liegt die Gewinnschwelle?} + +Bei durchschnittlich 10€ Einzahlung pro aktivem Nutzer und 1000 aktiven Nutzern monatlich: +\begin{itemize} + \item \textbf{Monatlicher Umsatz:} 10.000€ + \item \textbf{Betriebskosten:} 3.000€ (Server, Support, Marketing) + \item \textbf{Break-Even:} Nach 6 Monaten bei stetigem Nutzerwachstum +\end{itemize} + +\chapter{Deployment und Betrieb} + +\section{Container-Konfiguration} +Die Anwendung wird mit Docker containerisiert: + +\subsection{Backend Dockerfile} +\begin{lstlisting}[caption=Backend Dockerfile] +FROM eclipse-temurin:17-jdk-alpine AS build +WORKDIR /app +COPY gradle gradle +COPY gradlew build.gradle.kts settings.gradle.kts ./ +RUN ./gradlew dependencies --no-daemon +COPY src src +RUN ./gradlew bootJar --no-daemon + +FROM eclipse-temurin:17-jre-alpine +WORKDIR /app +COPY --from=build /app/build/libs/*.jar app.jar +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "app.jar"] +\end{lstlisting} + +\subsection{Frontend Dockerfile} +\begin{lstlisting}[caption=Frontend Dockerfile] +FROM node:18-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM nginx:alpine +COPY --from=build /app/dist/casino-frontend /usr/share/nginx/html +COPY nginx.conf /etc/nginx/nginx.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] +\end{lstlisting} + +\section{CI/CD-Pipeline} +Die Anwendung nutzt GitHub Actions für automatisierte Builds: + +\begin{lstlisting}[caption=GitHub Actions Workflow] +name: Build and Deploy + +on: + push: + branches: [main, develop] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + + - name: Run Backend Tests + working-directory: ./backend + run: ./gradlew test + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + + - name: Run Frontend Tests + working-directory: ./frontend + run: | + npm ci + npm run test:ci + + build: + needs: test + runs-on: ubuntu-latest + steps: + - name: Build Docker Images + run: | + docker build -t casino-backend ./backend + docker build -t casino-frontend ./frontend +\end{lstlisting} + +\section{Monitoring und Wartung} + +\subsection{Health Checks} +Spring Boot Actuator bietet Health-Endpoints: + +\begin{lstlisting}[language=Java, caption=Health Check Configuration] +@Component +public class DatabaseHealthIndicator implements HealthIndicator { + @Autowired + private DataSource dataSource; + + @Override + public Health health() { + try (Connection conn = dataSource.getConnection()) { + if (conn.isValid(1)) { + return Health.up() + .withDetail("database", "PostgreSQL") + .build(); + } + } catch (SQLException e) { + return Health.down() + .withException(e) + .build(); + } + return Health.down().build(); + } +} +\end{lstlisting} + +\subsection{Logging-Konfiguration} +Strukturiertes Logging mit SLF4J: + +\begin{lstlisting}[language=xml, caption=logback.xml] + + + + + %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n + + + + + + logs/casino.log + + logs/casino.%d{yyyy-MM-dd}.log + 30 + + + + %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + +\end{lstlisting} + +\chapter{Sicherheitskonzept} + +\section{Authentifizierung und Autorisierung} +Die Plattform implementiert ein mehrstufiges Sicherheitskonzept: + +\subsection{OAuth2/OpenID Connect} +Keycloak als Identity Provider bietet: +\begin{itemize} + \item Single Sign-On (SSO) + \item Multi-Factor Authentication (MFA) + \item Social Login (Google, GitHub) + \item Token-basierte Authentifizierung (JWT) +\end{itemize} + +\subsection{API-Sicherheit} +\begin{lstlisting}[language=Java, caption=Security Headers] +@Component +public class SecurityHeadersFilter implements Filter { + @Override + public void doFilter(ServletRequest request, + ServletResponse response, + FilterChain chain) { + HttpServletResponse httpResponse = + (HttpServletResponse) response; + + httpResponse.setHeader("X-Content-Type-Options", "nosniff"); + httpResponse.setHeader("X-Frame-Options", "DENY"); + httpResponse.setHeader("X-XSS-Protection", "1; mode=block"); + httpResponse.setHeader("Strict-Transport-Security", + "max-age=31536000; includeSubDomains"); + + chain.doFilter(request, response); + } +} +\end{lstlisting} + +\section{Datenschutz} +Die Anwendung erfüllt DSGVO-Anforderungen: + +\begin{itemize} + \item Verschlüsselte Datenspeicherung + \item Recht auf Datenlöschung + \item Datenportabilität + \item Audit-Logging aller Zugriffe + \item Cookie-Consent-Management +\end{itemize} + +\section{Zahlungssicherheit} +PCI-DSS-Compliance durch: +\begin{itemize} + \item Keine Speicherung von Kreditkartendaten + \item Stripe-Integration für Zahlungsverarbeitung + \item TLS-Verschlüsselung aller Transaktionen + \item Webhook-Validierung mit Signatur +\end{itemize} + +\chapter{Abschluss} + +\section{Projektziel} + +\subsection{Wurde das Projektziel erreicht?} +Das Projektziel wurde erfolgreich erreicht. Die Casino Gaming Platform wurde innerhalb der vorgegebenen 70 Stunden vollständig entwickelt und implementiert. + +\subsubsection{Soll-Ist Vergleich} +\begin{longtable}{|p{6cm}|p{3cm}|p{6cm}|} +\hline +\textbf{Anforderung} & \textbf{Status} & \textbf{Bemerkung} \\ +\hline +5 Casino-Spiele & \ding{51} Erreicht & Blackjack, Slots, Dice, Coinflip, Lootboxes \\ +\hline +OAuth2-Authentifizierung & \ding{51} Erreicht & GitHub und Google Integration \\ +\hline +Stripe-Zahlungssystem & \ding{51} Erreicht & Vollständig funktionstüchtig \\ +\hline +Responsive Design & \ding{51} Erreicht & Mobile-First Ansatz \\ +\hline +Transaktionshistorie & \ding{51} Erreicht & Vollständige Nachverfolgung \\ +\hline +DSGVO-Konformität & \ding{51} Erreicht & Datenschutz implementiert \\ +\hline +API-Dokumentation & \ding{51} Erreicht & Swagger/OpenAPI \\ +\hline +\end{longtable} + +\subsection{Änderungen zur anfänglichen Planung} +\begin{itemize} + \item \textbf{Poker-Spiel:} Wurde auf zukünftige Version verschoben aufgrund der Komplexität + \item \textbf{WebSocket-Integration:} Zusätzlich implementiert für Real-time Updates + \item \textbf{Docker-Containerisierung:} Früher als geplant eingeführt für bessere Entwicklungsumgebung +\end{itemize} + +\subsection{Einhaltung des zeitlichen Rahmens} +Der zeitliche Rahmen von 70 Stunden wurde eingehalten: + +\begin{itemize} + \item \textbf{Analyse \& Design:} 15 Stunden (geplant: 20 Stunden) + \item \textbf{Backend-Entwicklung:} 25 Stunden (geplant: 25 Stunden) + \item \textbf{Frontend-Entwicklung:} 20 Stunden (geplant: 15 Stunden) + \item \textbf{Testing \& QA:} 8 Stunden (geplant: 8 Stunden) + \item \textbf{Dokumentation:} 2 Stunden (geplant: 2 Stunden) +\end{itemize} + +\section{Fazit} + +\subsection{Teamarbeit} +\textbf{Wie hat die Teamarbeit funktioniert?} + +\begin{itemize} + \item \textbf{Positive Aspekte:} + \begin{itemize} + \item Gute Kommunikation über Scrum Daily Standups + \item Klare Aufgabenverteilung durch Jira-Tickets + \item Effektive Code-Reviews über Pull Requests + \item Konstruktive Problemlösungen im Team + \end{itemize} + + \item \textbf{Verbesserungspotential:} + \begin{itemize} + \item Besseres Ticket-Handling in der Anfangsphase + \item Weniger informelle Gespräche während Arbeitszeit + \item Frühzeitigere Integration von Komponenten + \end{itemize} +\end{itemize} + +\subsection{Persönlicher Lerngewinn} +\textbf{Was hat das Projekt mir persönlich gebracht?} + +\begin{itemize} + \item \textbf{Technische Kompetenzen:} + \begin{itemize} + \item Vertiefung in Angular 20 und moderne Frontend-Entwicklung + \item Praktische Erfahrung mit Spring Boot und Microservices + \item OAuth2 und JWT-basierte Authentifizierung + \item Container-Technologien (Docker, Docker Compose) + \item CI/CD-Pipelines mit GitHub Actions + \end{itemize} + + \item \textbf{Methodische Kompetenzen:} + \begin{itemize} + \item Agile Softwareentwicklung mit Scrum + \item Test-Driven Development (TDD) + \item Domain-Driven Design (DDD) + \item Clean Code Prinzipien + \end{itemize} + + \item \textbf{Projektmanagement:} + \begin{itemize} + \item Zeitmanagement bei komplexen Projekten + \item Risikomanagement und Problemlösung + \item Stakeholder-Kommunikation + \item Dokumentation und Präsentation + \end{itemize} +\end{itemize} + +\subsection{Ausblick} +Die entwickelte Casino Gaming Platform bietet eine solide Grundlage für weitere Entwicklungen. Die moderne Architektur und der saubere Code ermöglichen es, das System kontinuierlich zu erweitern und zu verbessern. + +\subsubsection{Geplante Erweiterungen} +\begin{itemize} + \item \textbf{Kurzfristig (3 Monate):} Mobile Apps für iOS und Android + \item \textbf{Mittelfristig (6 Monate):} Multiplayer-Funktionen und Turniere + \item \textbf{Langfristig (12 Monate):} KI-basierte Spielempfehlungen und erweiterte Analytics +\end{itemize} + +Das Projekt hat gezeigt, dass mit modernen Technologien und agilen Methoden auch komplexe Anwendungen effizient und qualitativ hochwertig entwickelt werden können. + +\appendix +\chapter{Anhang} + +\section{Glossar} +\begin{description} + \item[API] Application Programming Interface - Schnittstelle zur Kommunikation zwischen Softwarekomponenten + \item[CI/CD] Continuous Integration/Continuous Deployment - Automatisierte Build- und Deployment-Prozesse + \item[DDD] Domain-Driven Design - Softwaredesign-Ansatz + \item[DSGVO] Datenschutz-Grundverordnung + \item[JWT] JSON Web Token - Standard für sichere Informationsübertragung + \item[OAuth2] Autorisierungsframework für sichere API-Zugriffe + \item[PCI-DSS] Payment Card Industry Data Security Standard + \item[REST] Representational State Transfer - Architekturstil für Web-Services + \item[SSO] Single Sign-On - Einmalige Anmeldung für mehrere Dienste +\end{description} + +\section{Literaturverzeichnis} +\begin{enumerate} + \item Spring Boot Reference Documentation, Version 3.2, Spring Framework Team, 2024 + \item Angular Developer Guide, Version 20, Angular Team, Google, 2024 + \item Keycloak Server Administration Guide, Red Hat, 2024 + \item Stripe API Reference, Stripe Inc., 2024 + \item PostgreSQL Documentation, Version 17, PostgreSQL Global Development Group, 2024 + \item Docker Documentation, Docker Inc., 2024 + \item Clean Architecture, Robert C. Martin, Prentice Hall, 2017 + \item Domain-Driven Design, Eric Evans, Addison-Wesley, 2003 +\end{enumerate} + +\section{Abbildungsverzeichnis} +\begin{enumerate} + \item Systemarchitektur-Diagramm + \item ER-Diagramm der Datenbank + \item Sequenzdiagramm Authentifizierung + \item Klassendiagramm Backend + \item Komponentendiagramm Frontend +\end{enumerate} + +\section{Tabellenverzeichnis} +\begin{enumerate} + \item Projektphasen und Zeitaufwand + \item Technologie-Stack Übersicht + \item API-Endpoints Dokumentation + \item Testabdeckung pro Modul +\end{enumerate} + +\end{document} \ No newline at end of file -- 2.47.2 From 04bdb89a93561ae1ded42850a6c2cb4a4ec90986 Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 4 Jun 2025 11:54:41 +0200 Subject: [PATCH 2/4] chore: update labeler configuration for documentation files --- .gitea/labeler.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitea/labeler.yml b/.gitea/labeler.yml index a26346d..24987e1 100644 --- a/.gitea/labeler.yml +++ b/.gitea/labeler.yml @@ -12,3 +12,9 @@ ci: - changed-files: - any-glob-to-any-file: - ".gitea/**" + +docs: + - changed-files: + - any-glob-to-any-file: + - "docs/**" +g \ No newline at end of file -- 2.47.2 From 0b39eacc33ef9eed1c8a3fcb327c7bac5e732d63 Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 4 Jun 2025 11:55:51 +0200 Subject: [PATCH 3/4] chore: fix formatting in labeler configuration file --- .gitea/labeler.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitea/labeler.yml b/.gitea/labeler.yml index 24987e1..7cdb157 100644 --- a/.gitea/labeler.yml +++ b/.gitea/labeler.yml @@ -16,5 +16,4 @@ ci: docs: - changed-files: - any-glob-to-any-file: - - "docs/**" -g \ No newline at end of file + - "docs/**" \ No newline at end of file -- 2.47.2 From 17774fcdb2db6b0f78d0e322b95663a22959388f Mon Sep 17 00:00:00 2001 From: jank Date: Wed, 4 Jun 2025 12:04:40 +0200 Subject: [PATCH 4/4] chore: Add pipeline --- .gitea/workflows/docs.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .gitea/workflows/docs.yml diff --git a/.gitea/workflows/docs.yml b/.gitea/workflows/docs.yml new file mode 100644 index 0000000..585f0b2 --- /dev/null +++ b/.gitea/workflows/docs.yml @@ -0,0 +1,28 @@ +name: Build docs + +on: + push: + branches: [main] + +jobs: + build-docs: + runs-on: ubuntu-latest + container: + image: git.kjan.de/actions/runner-latex:latest + env: + # Edit here with the names of your latex file and directory (can use ".") + DIR: docs + FILE: projektdokumentation.tex + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: LaTeX compile + working-directory: ${{ env.DIR }} + run: latexmk -pdf -xelatex ${{ env.FILE }} + + - name: Upload artifacts + uses: https://git.kjan.de/actions/upload-artifact@v3 + with: + name: Doku + path: docs/projektdokumentation.pdf -- 2.47.2