feat(blackjack): implement game start and controls functionality #94
9 changed files with 320 additions and 54 deletions
|
@ -23,6 +23,7 @@ public class BlackJackService {
|
||||||
BlackJackGameEntity game = new BlackJackGameEntity();
|
BlackJackGameEntity game = new BlackJackGameEntity();
|
||||||
game.setUser(user);
|
game.setUser(user);
|
||||||
game.setBet(betAmount);
|
game.setBet(betAmount);
|
||||||
|
game.setState("IN_PROGRESS");
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
CardEntity playerCard = createRandomCard(game);
|
CardEntity playerCard = createRandomCard(game);
|
||||||
|
|
|
@ -3,20 +3,23 @@
|
||||||
<div class="container mx-auto px-4 py-6 space-y-8">
|
<div class="container mx-auto px-4 py-6 space-y-8">
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
||||||
<div class="lg:col-span-3 space-y-6 flex flex-col gap-4">
|
<div class="lg:col-span-3 space-y-6 flex flex-col gap-4">
|
||||||
<app-dealer-hand [cards]="dealerCards"></app-dealer-hand>
|
<app-dealer-hand [cards]="dealerCards()"></app-dealer-hand>
|
||||||
<app-player-hand [cards]="playerCards"></app-player-hand>
|
<app-player-hand [cards]="playerCards()"></app-player-hand>
|
||||||
<app-game-controls
|
@if (gameInProgress()) {
|
||||||
(hit)="onHit()"
|
<app-game-controls
|
||||||
(stand)="onStand()"
|
(hit)="onHit()"
|
||||||
(leave)="leaveGame()"
|
(stand)="onStand()"
|
||||||
></app-game-controls>
|
(leave)="leaveGame()"
|
||||||
|
></app-game-controls>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lg:col-span-1 space-y-6">
|
<div class="lg:col-span-1 space-y-6">
|
||||||
<app-game-info
|
<app-game-info
|
||||||
[balance]="balance()"
|
[balance]="balance()"
|
||||||
[currentBet]="currentBet"
|
[currentBet]="currentBet()"
|
||||||
(newGame)="onNewGame()"
|
[gameInProgress]="gameInProgress()"
|
||||||
|
(newGame)="onNewGame($event)"
|
||||||
></app-game-info>
|
></app-game-info>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,8 @@ import { DealerHandComponent } from './components/dealer-hand/dealer-hand.compon
|
||||||
import { PlayerHandComponent } from './components/player-hand/player-hand.component';
|
import { PlayerHandComponent } from './components/player-hand/player-hand.component';
|
||||||
import { GameControlsComponent } from './components/game-controls/game-controls.component';
|
import { GameControlsComponent } from './components/game-controls/game-controls.component';
|
||||||
import { GameInfoComponent } from './components/game-info/game-info.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({
|
@Component({
|
||||||
selector: 'app-blackjack',
|
selector: 'app-blackjack',
|
||||||
|
@ -28,16 +29,14 @@ import { Card } from './models/card.model';
|
||||||
export default class BlackjackComponent {
|
export default class BlackjackComponent {
|
||||||
private router = inject(Router);
|
private router = inject(Router);
|
||||||
private userService = inject(UserService);
|
private userService = inject(UserService);
|
||||||
|
private blackjackService = inject(BlackjackService);
|
||||||
|
|
||||||
dealerCards: Card[] = [
|
dealerCards = signal<Card[]>([]);
|
||||||
{ value: '2', suit: '♥', hidden: false },
|
playerCards = signal<Card[]>([]);
|
||||||
{ value: '3', suit: '♦', hidden: false },
|
currentBet = signal(0);
|
||||||
{ value: 'B', suit: '□', hidden: true },
|
|
||||||
];
|
|
||||||
|
|
||||||
playerCards: Card[] = [];
|
|
||||||
currentBet = 0;
|
|
||||||
balance = signal(0);
|
balance = signal(0);
|
||||||
|
currentGameId = signal<number | undefined>(undefined);
|
||||||
|
gameInProgress = signal(false);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.userService.getCurrentUser().subscribe((user) => {
|
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 {
|
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 {
|
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 {
|
leaveGame(): void {
|
||||||
this.router.navigate(['/home']);
|
this.router.navigate(['/home']);
|
||||||
}
|
}
|
||||||
|
|
||||||
onNewGame(): void {
|
|
||||||
// Implementation for new game
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { PlayingCardComponent } from '../playing-card/playing-card.component';
|
import { PlayingCardComponent } from '../playing-card/playing-card.component';
|
||||||
import { Card } from '../../models/card.model';
|
import { Card } from '../../models/blackjack.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dealer-hand',
|
selector: 'app-dealer-hand',
|
||||||
|
@ -12,12 +12,19 @@ import { Card } from '../../models/card.model';
|
||||||
<h3 class="section-heading text-2xl mb-4">Croupier's Karten</h3>
|
<h3 class="section-heading text-2xl mb-4">Croupier's Karten</h3>
|
||||||
<div class="card p-6 !bg-accent-red">
|
<div class="card p-6 !bg-accent-red">
|
||||||
<div class="flex justify-center gap-4 min-h-[160px] p-4 border-2 border-red-400 rounded-lg">
|
<div class="flex justify-center gap-4 min-h-[160px] p-4 border-2 border-red-400 rounded-lg">
|
||||||
<app-playing-card
|
@if (cards.length > 0) {
|
||||||
*ngFor="let card of cards"
|
@for (card of cards; track card) {
|
||||||
[value]="card.value"
|
<app-playing-card
|
||||||
[suit]="card.suit"
|
[rank]="card.rank"
|
||||||
[hidden]="card.hidden"
|
[suit]="card.suit"
|
||||||
></app-playing-card>
|
[hidden]="card.hidden"
|
||||||
|
></app-playing-card>
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
<div class="flex items-center justify-center text-white/70 text-lg font-medium">
|
||||||
|
Warte auf Spielstart...
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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 { CommonModule, CurrencyPipe } from '@angular/common';
|
||||||
|
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-game-info',
|
selector: 'app-game-info',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, CurrencyPipe],
|
imports: [CommonModule, CurrencyPipe, ReactiveFormsModule],
|
||||||
template: `
|
template: `
|
||||||
<div class="card p-4">
|
<div class="card p-4">
|
||||||
<h3 class="section-heading text-xl mb-4">Spiel Informationen</h3>
|
<h3 class="section-heading text-xl mb-4">Spiel Informationen</h3>
|
||||||
|
@ -19,14 +28,112 @@ import { CommonModule, CurrencyPipe } from '@angular/common';
|
||||||
{{ currentBet | currency: 'EUR' }}
|
{{ currentBet | currency: 'EUR' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<button class="button-primary w-full py-2" (click)="newGame.emit()">Neues Spiel</button>
|
|
||||||
|
@if (!gameInProgress) {
|
||||||
|
<div class="grid grid-cols-2 gap-2 mb-4">
|
||||||
|
<button
|
||||||
|
(click)="setBetAmount(0.1)"
|
||||||
|
class="button-primary py-2 text-sm"
|
||||||
|
[disabled]="gameInProgress"
|
||||||
|
>
|
||||||
|
10%
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="setBetAmount(0.25)"
|
||||||
|
class="button-primary py-2 text-sm"
|
||||||
|
[disabled]="gameInProgress"
|
||||||
|
>
|
||||||
|
25%
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="setBetAmount(0.5)"
|
||||||
|
class="button-primary py-2 text-sm"
|
||||||
|
[disabled]="gameInProgress"
|
||||||
|
>
|
||||||
|
50%
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="setBetAmount(1)"
|
||||||
|
class="button-primary py-2 text-sm"
|
||||||
|
[disabled]="gameInProgress"
|
||||||
|
>
|
||||||
|
100%
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<form [formGroup]="betForm" (ngSubmit)="onSubmit()" class="space-y-2">
|
||||||
|
<div class="space-y-1">
|
||||||
|
<label for="bet" class="text-sm text-text-secondary">Einsatz</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id="bet"
|
||||||
|
formControlName="bet"
|
||||||
|
class="w-full px-3 py-2 bg-deep-blue-light text-white rounded focus:outline-none focus:ring-2 focus:ring-emerald"
|
||||||
|
[min]="1"
|
||||||
|
[max]="balance"
|
||||||
|
step="0.01"
|
||||||
|
/>
|
||||||
|
@if (betForm.get('bet')?.errors?.['required'] && betForm.get('bet')?.touched) {
|
||||||
|
<span class="text-xs text-accent-red">Bitte geben Sie einen Einsatz ein</span>
|
||||||
|
}
|
||||||
|
@if (betForm.get('bet')?.errors?.['min'] && betForm.get('bet')?.touched) {
|
||||||
|
<span class="text-xs text-accent-red">Mindestens 1€ setzen</span>
|
||||||
|
}
|
||||||
|
@if (betForm.get('bet')?.errors?.['max'] && betForm.get('bet')?.touched) {
|
||||||
|
<span class="text-xs text-accent-red">Nicht genügend Guthaben</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="button-primary w-full py-2"
|
||||||
|
[disabled]="!betForm.valid || gameInProgress"
|
||||||
|
>
|
||||||
|
Neues Spiel
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class GameInfoComponent {
|
export class GameInfoComponent implements OnChanges {
|
||||||
@Input() balance = 0;
|
@Input() balance = 0;
|
||||||
@Input() currentBet = 0;
|
@Input() currentBet = 0;
|
||||||
@Output() newGame = new EventEmitter<void>();
|
@Input() gameInProgress = false;
|
||||||
|
@Output() newGame = new EventEmitter<number>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { PlayingCardComponent } from '../playing-card/playing-card.component';
|
import { PlayingCardComponent } from '../playing-card/playing-card.component';
|
||||||
import { Card } from '../../models/card.model';
|
import { Card } from '../../models/blackjack.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-player-hand',
|
selector: 'app-player-hand',
|
||||||
|
@ -14,12 +14,19 @@ import { Card } from '../../models/card.model';
|
||||||
<div
|
<div
|
||||||
class="flex justify-center gap-4 min-h-[160px] p-4 border-2 border-emerald-400 rounded-lg"
|
class="flex justify-center gap-4 min-h-[160px] p-4 border-2 border-emerald-400 rounded-lg"
|
||||||
>
|
>
|
||||||
<app-playing-card
|
@if (cards.length > 0) {
|
||||||
*ngFor="let card of cards"
|
@for (card of cards; track card) {
|
||||||
[value]="card.value"
|
<app-playing-card
|
||||||
[suit]="card.suit"
|
[rank]="card.rank"
|
||||||
[hidden]="card.hidden"
|
[suit]="card.suit"
|
||||||
></app-playing-card>
|
[hidden]="card.hidden"
|
||||||
|
></app-playing-card>
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
<div class="flex items-center justify-center text-white/70 text-lg font-medium">
|
||||||
|
Platziere eine Wette um zu spielen...
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { suitSymbols, Suit } from '../../models/blackjack.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-playing-card',
|
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="w-24 h-36 rounded-lg p-2 relative flex flex-col justify-between shadow-lg"
|
||||||
[class]="hidden ? 'bg-red-800' : 'bg-white'"
|
[class]="hidden ? 'bg-red-800' : 'bg-white'"
|
||||||
>
|
>
|
||||||
<span *ngIf="!hidden" class="text-xl font-bold text-accent-red">{{ value }}</span>
|
@if (!hidden) {
|
||||||
<span
|
<span class="text-xl font-bold text-accent-red">{{ getDisplayRank(rank) }}</span>
|
||||||
*ngIf="!hidden"
|
}
|
||||||
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-accent-red"
|
@if (!hidden) {
|
||||||
>{{ suit }}</span
|
<span
|
||||||
>
|
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-accent-red"
|
||||||
<span *ngIf="!hidden" class="text-xl font-bold text-accent-red self-end rotate-180">{{
|
>{{ getSuitSymbol(suit) }}</span
|
||||||
value
|
>
|
||||||
}}</span>
|
}
|
||||||
|
@if (!hidden) {
|
||||||
|
<span class="text-xl font-bold text-accent-red self-end rotate-180">{{
|
||||||
|
getDisplayRank(rank)
|
||||||
|
}}</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class PlayingCardComponent {
|
export class PlayingCardComponent {
|
||||||
@Input({ required: true }) value!: string;
|
@Input({ required: true }) rank!: string;
|
||||||
@Input({ required: true }) suit!: string;
|
@Input({ required: true }) suit!: Suit;
|
||||||
@Input({ required: true }) hidden!: boolean;
|
@Input({ required: true }) hidden!: boolean;
|
||||||
|
|
||||||
|
protected getSuitSymbol(suit: Suit): string {
|
||||||
|
return suitSymbols[suit];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getDisplayRank(rank: string): string {
|
||||||
|
const rankMap: Record<string, string> = {
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<Suit, string> = {
|
||||||
|
HEARTS: '♥',
|
||||||
|
DIAMONDS: '♦',
|
||||||
|
CLUBS: '♣',
|
||||||
|
SPADES: '♠',
|
||||||
|
};
|
|
@ -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<BlackjackGame> {
|
||||||
|
return this.http
|
||||||
|
.post<BlackjackGame>('/backend/blackjack/start', { betAmount: bet }, { responseType: 'json' })
|
||||||
|
.pipe(
|
||||||
|
catchError((error) => {
|
||||||
|
console.error('Start game error:', error);
|
||||||
|
throw error;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
hit(gameId: number): Observable<BlackjackGame> {
|
||||||
|
return this.http
|
||||||
|
.post<BlackjackGame>(`/backend/blackjack/${gameId}/hit`, {}, { responseType: 'json' })
|
||||||
|
.pipe(
|
||||||
|
catchError((error) => {
|
||||||
|
console.error('Hit error:', error);
|
||||||
|
throw error;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
stand(gameId: number): Observable<BlackjackGame> {
|
||||||
|
return this.http
|
||||||
|
.post<BlackjackGame>(`/backend/blackjack/${gameId}/stand`, {}, { responseType: 'json' })
|
||||||
|
.pipe(
|
||||||
|
catchError((error) => {
|
||||||
|
console.error('Stand error:', error);
|
||||||
|
throw error;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue