diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java
index ba5e7d1..cca78e4 100644
--- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java
+++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java
@@ -23,6 +23,7 @@ public class BlackJackService {
BlackJackGameEntity game = new BlackJackGameEntity();
game.setUser(user);
game.setBet(betAmount);
+ game.setState("IN_PROGRESS");
for (int i = 0; i < 2; i++) {
CardEntity playerCard = createRandomCard(game);
diff --git a/frontend/src/app/feature/game/blackjack/blackjack.component.html b/frontend/src/app/feature/game/blackjack/blackjack.component.html
index db4d698..ae130d4 100644
--- a/frontend/src/app/feature/game/blackjack/blackjack.component.html
+++ b/frontend/src/app/feature/game/blackjack/blackjack.component.html
@@ -3,20 +3,23 @@
-
-
-
+
+
+ @if (gameInProgress()) {
+
+ }
diff --git a/frontend/src/app/feature/game/blackjack/blackjack.component.ts b/frontend/src/app/feature/game/blackjack/blackjack.component.ts
index 4e66587..174c358 100644
--- a/frontend/src/app/feature/game/blackjack/blackjack.component.ts
+++ b/frontend/src/app/feature/game/blackjack/blackjack.component.ts
@@ -8,7 +8,8 @@ import { DealerHandComponent } from './components/dealer-hand/dealer-hand.compon
import { PlayerHandComponent } from './components/player-hand/player-hand.component';
import { GameControlsComponent } from './components/game-controls/game-controls.component';
import { GameInfoComponent } from './components/game-info/game-info.component';
-import { Card } from './models/card.model';
+import { Card, BlackjackGame } from './models/blackjack.model';
+import { BlackjackService } from './services/blackjack.service';
@Component({
selector: 'app-blackjack',
@@ -28,16 +29,14 @@ import { Card } from './models/card.model';
export default class BlackjackComponent {
private router = inject(Router);
private userService = inject(UserService);
+ private blackjackService = inject(BlackjackService);
- dealerCards: Card[] = [
- { value: '2', suit: '♥', hidden: false },
- { value: '3', suit: '♦', hidden: false },
- { value: 'B', suit: '□', hidden: true },
- ];
-
- playerCards: Card[] = [];
- currentBet = 0;
+ dealerCards = signal
([]);
+ playerCards = signal([]);
+ currentBet = signal(0);
balance = signal(0);
+ currentGameId = signal(undefined);
+ gameInProgress = signal(false);
constructor() {
this.userService.getCurrentUser().subscribe((user) => {
@@ -45,19 +44,65 @@ export default class BlackjackComponent {
});
}
+ private updateGameState(game: BlackjackGame) {
+ console.log('Game state update:', game);
+ this.currentGameId.set(game.id);
+ this.currentBet.set(game.bet);
+ this.gameInProgress.set(game.state === 'IN_PROGRESS');
+
+ this.dealerCards.set(
+ game.dealerCards.map((card, index) => ({
+ ...card,
+ hidden: index === 1 && game.state === 'IN_PROGRESS',
+ }))
+ );
+
+ this.playerCards.set(
+ game.playerCards.map((card) => ({
+ ...card,
+ hidden: false,
+ }))
+ );
+ }
+
+ onNewGame(bet: number): void {
+ this.blackjackService.startGame(bet).subscribe({
+ next: (game) => {
+ this.updateGameState(game);
+ },
+ error: (error) => {
+ console.error('Failed to start game:', error);
+ },
+ });
+ }
+
onHit(): void {
- // Implementation for hit action
+ if (!this.currentGameId()) return;
+
+ this.blackjackService.hit(this.currentGameId()!).subscribe({
+ next: (game) => {
+ this.updateGameState(game);
+ },
+ error: (error) => {
+ console.error('Failed to hit:', error);
+ },
+ });
}
onStand(): void {
- // Implementation for stand action
+ if (!this.currentGameId()) return;
+
+ this.blackjackService.stand(this.currentGameId()!).subscribe({
+ next: (game) => {
+ this.updateGameState(game);
+ },
+ error: (error) => {
+ console.error('Failed to stand:', error);
+ },
+ });
}
leaveGame(): void {
this.router.navigate(['/home']);
}
-
- onNewGame(): void {
- // Implementation for new game
- }
}
diff --git a/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts b/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts
index 6b8cdce..89517a1 100644
--- a/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts
+++ b/frontend/src/app/feature/game/blackjack/components/dealer-hand/dealer-hand.component.ts
@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PlayingCardComponent } from '../playing-card/playing-card.component';
-import { Card } from '../../models/card.model';
+import { Card } from '../../models/blackjack.model';
@Component({
selector: 'app-dealer-hand',
@@ -12,12 +12,19 @@ import { Card } from '../../models/card.model';
Croupier's Karten
-
+ @if (cards.length > 0) {
+ @for (card of cards; track card) {
+
+ }
+ } @else {
+
+ Warte auf Spielstart...
+
+ }
diff --git a/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts b/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts
index 8f9d532..e35bf73 100644
--- a/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts
+++ b/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts
@@ -1,10 +1,19 @@
-import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
+import {
+ ChangeDetectionStrategy,
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ Output,
+ SimpleChanges,
+} from '@angular/core';
import { CommonModule, CurrencyPipe } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
@Component({
selector: 'app-game-info',
standalone: true,
- imports: [CommonModule, CurrencyPipe],
+ imports: [CommonModule, CurrencyPipe, ReactiveFormsModule],
template: `
Spiel Informationen
@@ -19,14 +28,112 @@ import { CommonModule, CurrencyPipe } from '@angular/common';
{{ currentBet | currency: 'EUR' }}
-
+
+ @if (!gameInProgress) {
+
+
+
+
+
+
+ }
+
+
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class GameInfoComponent {
+export class GameInfoComponent implements OnChanges {
@Input() balance = 0;
@Input() currentBet = 0;
- @Output() newGame = new EventEmitter();
+ @Input() gameInProgress = false;
+ @Output() newGame = new EventEmitter();
+
+ betForm: FormGroup;
+
+ constructor(private fb: FormBuilder) {
+ this.betForm = this.fb.group({
+ bet: ['', [Validators.required, Validators.min(1)]],
+ });
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes['balance']) {
+ this.betForm
+ .get('bet')
+ ?.setValidators([Validators.required, Validators.min(1), Validators.max(this.balance)]);
+ this.betForm.get('bet')?.updateValueAndValidity();
+ }
+ }
+
+ setBetAmount(percentage: number) {
+ const betAmount = Math.floor(this.balance * percentage * 100) / 100;
+ if (betAmount >= 1) {
+ this.betForm.patchValue({ bet: betAmount });
+ }
+ }
+
+ onSubmit() {
+ if (this.betForm.valid) {
+ const betAmount = parseFloat(this.betForm.value.bet);
+ if (betAmount <= this.balance) {
+ this.newGame.emit(betAmount);
+ this.betForm.reset();
+ }
+ }
+ }
}
diff --git a/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts b/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts
index 2dc50c0..e158f67 100644
--- a/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts
+++ b/frontend/src/app/feature/game/blackjack/components/player-hand/player-hand.component.ts
@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PlayingCardComponent } from '../playing-card/playing-card.component';
-import { Card } from '../../models/card.model';
+import { Card } from '../../models/blackjack.model';
@Component({
selector: 'app-player-hand',
@@ -14,12 +14,19 @@ import { Card } from '../../models/card.model';
-
+ @if (cards.length > 0) {
+ @for (card of cards; track card) {
+
+ }
+ } @else {
+
+ Platziere eine Wette um zu spielen...
+
+ }
diff --git a/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts b/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts
index dc93df8..186ac9b 100644
--- a/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts
+++ b/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts
@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
+import { suitSymbols, Suit } from '../../models/blackjack.model';
@Component({
selector: 'app-playing-card',
@@ -10,21 +11,49 @@ import { CommonModule } from '@angular/common';
class="w-24 h-36 rounded-lg p-2 relative flex flex-col justify-between shadow-lg"
[class]="hidden ? 'bg-red-800' : 'bg-white'"
>
- {{ value }}
- {{ suit }}
- {{
- value
- }}
+ @if (!hidden) {
+ {{ getDisplayRank(rank) }}
+ }
+ @if (!hidden) {
+ {{ getSuitSymbol(suit) }}
+ }
+ @if (!hidden) {
+ {{
+ getDisplayRank(rank)
+ }}
+ }
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PlayingCardComponent {
- @Input({ required: true }) value!: string;
- @Input({ required: true }) suit!: string;
+ @Input({ required: true }) rank!: string;
+ @Input({ required: true }) suit!: Suit;
@Input({ required: true }) hidden!: boolean;
+
+ protected getSuitSymbol(suit: Suit): string {
+ return suitSymbols[suit];
+ }
+
+ protected getDisplayRank(rank: string): string {
+ const rankMap: Record = {
+ TWO: '2',
+ THREE: '3',
+ FOUR: '4',
+ FIVE: '5',
+ SIX: '6',
+ SEVEN: '7',
+ EIGHT: '8',
+ NINE: '9',
+ TEN: '10',
+ JACK: 'J',
+ QUEEN: 'Q',
+ KING: 'K',
+ ACE: 'A',
+ };
+ return rankMap[rank] || rank;
+ }
}
diff --git a/frontend/src/app/feature/game/blackjack/models/blackjack.model.ts b/frontend/src/app/feature/game/blackjack/models/blackjack.model.ts
new file mode 100644
index 0000000..55f2ee1
--- /dev/null
+++ b/frontend/src/app/feature/game/blackjack/models/blackjack.model.ts
@@ -0,0 +1,23 @@
+export type Suit = 'HEARTS' | 'DIAMONDS' | 'CLUBS' | 'SPADES';
+
+export interface Card {
+ suit: Suit;
+ rank: string;
+ hidden: boolean;
+}
+
+export interface BlackjackGame {
+ id: number;
+ state: string;
+ bet: number;
+ playerCards: Card[];
+ dealerCards: Card[];
+ userId: number;
+}
+
+export const suitSymbols: Record = {
+ HEARTS: '♥',
+ DIAMONDS: '♦',
+ CLUBS: '♣',
+ SPADES: '♠',
+};
diff --git a/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts b/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts
new file mode 100644
index 0000000..86ab7cf
--- /dev/null
+++ b/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts
@@ -0,0 +1,44 @@
+import { Injectable, inject } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable, catchError } from 'rxjs';
+import { BlackjackGame } from '../models/blackjack.model';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class BlackjackService {
+ private http = inject(HttpClient);
+
+ startGame(bet: number): Observable {
+ return this.http
+ .post('/backend/blackjack/start', { betAmount: bet }, { responseType: 'json' })
+ .pipe(
+ catchError((error) => {
+ console.error('Start game error:', error);
+ throw error;
+ })
+ );
+ }
+
+ hit(gameId: number): Observable {
+ return this.http
+ .post(`/backend/blackjack/${gameId}/hit`, {}, { responseType: 'json' })
+ .pipe(
+ catchError((error) => {
+ console.error('Hit error:', error);
+ throw error;
+ })
+ );
+ }
+
+ stand(gameId: number): Observable {
+ return this.http
+ .post(`/backend/blackjack/${gameId}/stand`, {}, { responseType: 'json' })
+ .pipe(
+ catchError((error) => {
+ console.error('Stand error:', error);
+ throw error;
+ })
+ );
+ }
+}