feat: add game state enum and refactor game components
This commit is contained in:
parent
349e4ce1ec
commit
4b569157aa
10 changed files with 105 additions and 115 deletions
|
@ -1,6 +1,8 @@
|
|||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Card } from '../../models/blackjack.model';
|
||||
import { GameState } from '../../../../../enum/gameState';
|
||||
import { GameControlsService } from '../../services/game-controls.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-game-controls',
|
||||
|
@ -11,10 +13,10 @@ import { Card } from '../../models/blackjack.model';
|
|||
<div class="flex justify-center text-lg mb-5">
|
||||
<div class="card p-4">
|
||||
<div class="text-emerald font-bold mb-1">
|
||||
Deine Punkte: {{ calculateHandValue(playerCards) }}
|
||||
Deine Punkte: {{ gameControlsService.calculateHandValue(playerCards) }}
|
||||
</div>
|
||||
<div class="text-text-secondary">
|
||||
Status: <span [class]="getStatusClass(gameState)">{{ getStatusText(gameState) }}</span>
|
||||
Status: <span [class]="gameControlsService.getStatusClass(gameState)">{{ gameControlsService.getStatusText(gameState) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -22,7 +24,7 @@ import { Card } from '../../models/blackjack.model';
|
|||
<button
|
||||
(click)="hit.emit()"
|
||||
class="button-primary px-8 py-4 text-lg font-medium min-w-[120px] relative"
|
||||
[disabled]="gameState !== 'IN_PROGRESS' || isActionInProgress"
|
||||
[disabled]="gameState !== GameState.IN_PROGRESS || isActionInProgress"
|
||||
[class.opacity-50]="isActionInProgress"
|
||||
>
|
||||
<span [class.invisible]="isActionInProgress">Ziehen</span>
|
||||
|
@ -37,7 +39,7 @@ import { Card } from '../../models/blackjack.model';
|
|||
<button
|
||||
(click)="stand.emit()"
|
||||
class="button-primary px-8 py-4 text-lg font-medium min-w-[120px] relative"
|
||||
[disabled]="gameState !== 'IN_PROGRESS' || isActionInProgress"
|
||||
[disabled]="gameState !== GameState.IN_PROGRESS || isActionInProgress"
|
||||
[class.opacity-50]="isActionInProgress"
|
||||
>
|
||||
<span [class.invisible]="isActionInProgress">Halten</span>
|
||||
|
@ -52,7 +54,7 @@ import { Card } from '../../models/blackjack.model';
|
|||
<button
|
||||
(click)="doubleDown.emit()"
|
||||
class="button-primary px-8 py-4 text-lg font-medium min-w-[120px] relative"
|
||||
[disabled]="gameState !== 'IN_PROGRESS' || playerCards.length !== 2 || isActionInProgress"
|
||||
[disabled]="gameState !== GameState.IN_PROGRESS || playerCards.length !== 2 || isActionInProgress"
|
||||
[class.opacity-50]="isActionInProgress"
|
||||
>
|
||||
<span [class.invisible]="isActionInProgress">Verdoppeln</span>
|
||||
|
@ -79,77 +81,15 @@ import { Card } from '../../models/blackjack.model';
|
|||
})
|
||||
export class GameControlsComponent {
|
||||
@Input() playerCards: Card[] = [];
|
||||
@Input() gameState = 'IN_PROGRESS';
|
||||
@Input() isActionInProgress = false;
|
||||
@Input() gameState: GameState = GameState.IN_PROGRESS;
|
||||
@Input() isActionInProgress: boolean = false;
|
||||
|
||||
@Output() hit = new EventEmitter<void>();
|
||||
@Output() stand = new EventEmitter<void>();
|
||||
@Output() doubleDown = new EventEmitter<void>();
|
||||
@Output() leave = new EventEmitter<void>();
|
||||
|
||||
calculateHandValue(cards: Card[]): number {
|
||||
let sum = 0;
|
||||
let aceCount = 0;
|
||||
protected readonly GameState = GameState;
|
||||
|
||||
const rankValues: Record<string, number> = {
|
||||
TWO: 2,
|
||||
THREE: 3,
|
||||
FOUR: 4,
|
||||
FIVE: 5,
|
||||
SIX: 6,
|
||||
SEVEN: 7,
|
||||
EIGHT: 8,
|
||||
NINE: 9,
|
||||
TEN: 10,
|
||||
JACK: 10,
|
||||
QUEEN: 10,
|
||||
KING: 10,
|
||||
ACE: 11,
|
||||
};
|
||||
|
||||
for (const card of cards) {
|
||||
if (!card.hidden) {
|
||||
const value = rankValues[card.rank] || 0;
|
||||
sum += value;
|
||||
if (card.rank === 'ACE') {
|
||||
aceCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (sum > 21 && aceCount > 0) {
|
||||
sum -= 10;
|
||||
aceCount--;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
getStatusText(state: string): string {
|
||||
switch (state) {
|
||||
case 'IN_PROGRESS':
|
||||
return 'Spiel läuft';
|
||||
case 'PLAYER_WON':
|
||||
return 'Gewonnen!';
|
||||
case 'PLAYER_LOST':
|
||||
return 'Verloren!';
|
||||
case 'DRAW':
|
||||
return 'Unentschieden!';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
getStatusClass(state: string): string {
|
||||
switch (state) {
|
||||
case 'PLAYER_WON':
|
||||
return 'text-emerald';
|
||||
case 'PLAYER_LOST':
|
||||
return 'text-accent-red';
|
||||
case 'DRAW':
|
||||
return 'text-yellow-400';
|
||||
default:
|
||||
return 'text-white';
|
||||
}
|
||||
}
|
||||
constructor(protected gameControlsService: GameControlsService) {}
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/* No custom styles needed */
|
|
@ -1,22 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GameResultComponent } from './game-result.component';
|
||||
|
||||
describe('GameResultComponent', () => {
|
||||
let component: GameResultComponent;
|
||||
let fixture: ComponentFixture<GameResultComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [GameResultComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GameResultComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,7 @@
|
|||
import { ChangeDetectionStrategy, Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { CommonModule, CurrencyPipe } from '@angular/common';
|
||||
import { animate, style, transition, trigger } from '@angular/animations';
|
||||
import { GameState } from '../../../../../enum/gameState';
|
||||
|
||||
@Component({
|
||||
selector: 'app-game-result',
|
||||
|
@ -55,7 +56,6 @@ import { animate, style, transition, trigger } from '@angular/animations';
|
|||
</div>
|
||||
</div>
|
||||
`,
|
||||
styleUrls: ['./game-result.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
animations: [
|
||||
trigger('fadeInOut', [
|
||||
|
@ -74,7 +74,7 @@ import { animate, style, transition, trigger } from '@angular/animations';
|
|||
],
|
||||
})
|
||||
export class GameResultComponent {
|
||||
@Input() gameState = '';
|
||||
@Input() gameState: GameState = GameState.IN_PROGRESS;
|
||||
@Input() amount = 0;
|
||||
@Input() set show(value: boolean) {
|
||||
console.log('GameResultComponent show input changed:', value, 'gameState:', this.gameState);
|
||||
|
@ -86,15 +86,15 @@ export class GameResultComponent {
|
|||
visible = false;
|
||||
|
||||
get isWin(): boolean {
|
||||
return this.gameState === 'PLAYER_WON';
|
||||
return this.gameState === GameState.PLAYER_WON;
|
||||
}
|
||||
|
||||
get isLoss(): boolean {
|
||||
return this.gameState === 'PLAYER_LOST';
|
||||
return this.gameState === GameState.PLAYER_LOST;
|
||||
}
|
||||
|
||||
get isDraw(): boolean {
|
||||
return this.gameState === 'DRAW';
|
||||
return this.gameState === GameState.DRAW;
|
||||
}
|
||||
|
||||
getResultTitle(): string {
|
||||
|
|
Reference in a new issue