diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.html b/frontend/src/app/feature/game/coinflip/coinflip.component.html index 8dd6be8..671bc31 100644 --- a/frontend/src/app/feature/game/coinflip/coinflip.component.html +++ b/frontend/src/app/feature/game/coinflip/coinflip.component.html @@ -5,11 +5,13 @@ @if (gameResult()) {

- {{ gameResult()?.isWin ? 'Du hast gewonnen!' : 'Du hast verloren' }} + {{ gameResult()?.isWin ? 'You Won!' : 'You Lost' }}

- Münze zeigt: - {{ gameResult()?.coinSide === 'HEAD' ? 'KOPF' : 'ZAHL' }} + Coin landed on: + {{ + gameResult()?.coinSide === 'HEAD' ? 'HEAD' : 'TAILS' + }}

@if (gameResult()?.isWin) {

@@ -33,7 +35,7 @@

-
KOPF
+
HEAD
@@ -41,7 +43,7 @@ class="back coin-side bg-gray-700 flex items-center justify-center text-2xl font-bold text-white" > - ZAHL + TAILS
@@ -54,7 +56,7 @@ class="button-primary py-3 px-6 relative text-lg" [class.opacity-50]="gameInProgress()" > - Auf ZAHL setzen + Bet TAILS @@ -70,11 +72,11 @@
-

Spielinformationen

+

Game Information

- Aktueller Einsatz: + Current Bet: @@ -82,7 +84,7 @@
- Dein Guthaben: + Your Balance: {{ balance() | currency: 'EUR' }} @@ -101,9 +103,9 @@
- + Darf Guthaben nicht überschreitenCannot exceed balance
-

Spielregeln

+

How to Play

    -
  • • Wähle deinen Einsatzbetrag
  • -
  • • Wähle Kopf oder Zahl
  • -
  • • Gewinne das Doppelte deines Einsatzes bei richtiger Wahl
  • +
  • • Choose your bet amount
  • +
  • • Select Heads or Tails
  • +
  • • Win double your bet if correct
diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.ts b/frontend/src/app/feature/game/coinflip/coinflip.component.ts index 112a300..1766e4d 100644 --- a/frontend/src/app/feature/game/coinflip/coinflip.component.ts +++ b/frontend/src/app/feature/game/coinflip/coinflip.component.ts @@ -44,14 +44,14 @@ export default class CoinflipComponent implements OnInit { private coinflipSound?: HTMLAudioElement; ngOnInit(): void { - // Abonniere Benutzerupdates für Echtzeitaktualisierungen des Guthabens + // Subscribe to user updates for real-time balance changes this.authService.userSubject.subscribe((user) => { if (user) { this.balance.set(user.balance); } }); - // Initialisiere Münzwurf-Sound + // Initialize coinflip sound this.coinflipSound = new Audio('/sounds/coinflip.mp3'); } @@ -65,26 +65,26 @@ export default class CoinflipComponent implements OnInit { const inputElement = event.target as HTMLInputElement; let value = Number(inputElement.value); - // Setze ungültigen Einsatz-Status zurück + // Reset invalid bet state this.isInvalidBet.set(false); - // Erzwinge Mindesteinsatz von 1 + // Enforce minimum bet of 1 if (value <= 0) { value = 1; } - // Begrenze Einsatz auf verfügbares Guthaben und zeige Feedback + // Cap bet at available balance and show feedback if (value > this.balance()) { value = this.balance(); - // Visuelles Feedback anzeigen + // Show visual feedback this.isInvalidBet.set(true); - // Zeige den Fehler kurz an + // Indicate the error briefly setTimeout(() => this.isInvalidBet.set(false), 800); - // Aktualisiere das Eingabefeld direkt, um dem Benutzer den maximalen Wert anzuzeigen + // Update the input field directly to show the user the max value inputElement.value = String(value); } - // Aktualisiere Signale + // Update signals this.betInputValue.set(value); this.currentBet.set(value); } @@ -100,34 +100,34 @@ export default class CoinflipComponent implements OnInit { private placeBet(side: 'HEAD' | 'TAILS') { if (this.gameInProgress() || this.isActionInProgress()) return; - // Setze vorheriges Ergebnis zurück + // Reset previous result this.gameResult.set(null); this.errorMessage.set(''); - // Setze Spielstatus + // Set game state this.gameInProgress.set(true); this.isActionInProgress.set(true); - // Spiele Einsatz-Sound + // Play bet sound this.audioService.playBetSound(); - // Erstelle Einsatz-Anfrage + // Create bet request const request: CoinflipRequest = { betAmount: this.currentBet(), coinSide: side, }; - // API aufrufen + // Call API this.http .post('/backend/coinflip', request) .pipe( catchError((error) => { - console.error('Fehler beim Spielen von Coinflip:', error); + console.error('Error playing coinflip:', error); if (error.status === 400 && error.error.message.includes('insufficient')) { - this.errorMessage.set('Unzureichendes Guthaben'); + this.errorMessage.set('Insufficient funds'); } else { - this.errorMessage.set('Ein Fehler ist aufgetreten. Bitte versuche es erneut.'); + this.errorMessage.set('An error occurred. Please try again.'); } this.gameInProgress.set(false); @@ -140,37 +140,37 @@ export default class CoinflipComponent implements OnInit { .subscribe((result) => { if (!result) return; - console.log('API-Antwort:', result); + console.log('API response:', result); - // Behebe mögliche Inkonsistenzen bei der Eigenschaftenbenennung vom Backend + // Fix potential property naming inconsistency from the backend const fixedResult: CoinflipGame = { isWin: result.isWin ?? result.win, payout: result.payout, coinSide: result.coinSide, }; - console.log('Korrigiertes Ergebnis:', fixedResult); + console.log('Fixed result:', fixedResult); - // Spiele Münzwurf-Animation und -Sound + // Play coin flip animation and sound this.playCoinFlipAnimation(fixedResult.coinSide); - // Setze Ergebnis nach Abschluss der Animation + // Set result after animation completes setTimeout(() => { this.gameResult.set(fixedResult); - // Aktualisiere Guthaben mit neuem Wert vom Auth-Service + // Update balance with new value from auth service this.authService.loadCurrentUser(); - // Spiele Gewinn-Sound, wenn der Spieler gewonnen hat + // Play win sound if player won if (fixedResult.isWin) { this.audioService.playWinSound(); } - // Setze Spielstatus nach Anzeigen des Ergebnisses zurück + // Reset game state after showing result setTimeout(() => { this.gameInProgress.set(false); }, 1500); - }, 1100); // Kurz nach Ende der Animation + }, 1100); // Just after animation ends }); } @@ -179,50 +179,48 @@ export default class CoinflipComponent implements OnInit { const coinEl = this.coinElement.nativeElement; - // Setze bestehende Animationen zurück + // Reset any existing animations coinEl.classList.remove('animate-to-heads', 'animate-to-tails'); - // Setze alle Inline-Styles von vorherigen Animationen zurück + // Reset any inline styles from previous animations coinEl.style.transform = ''; - // Erzwinge Reflow, um Animation neu zu starten + // Force a reflow to restart animation void coinEl.offsetWidth; - // Spiele Münzwurf-Sound + // Play flip sound if (this.coinflipSound) { this.coinflipSound.currentTime = 0; - this.coinflipSound - .play() - .catch((err) => console.error('Fehler beim Abspielen des Sounds:', err)); + this.coinflipSound.play().catch((err) => console.error('Error playing sound:', err)); } - // Füge passende Animationsklasse basierend auf dem Ergebnis hinzu + // Add appropriate animation class based on result if (result === 'HEAD') { coinEl.classList.add('animate-to-heads'); } else { coinEl.classList.add('animate-to-tails'); } - console.log(`Animation angewendet für Ergebnis: ${result}`); + console.log(`Animation applied for result: ${result}`); } /** - * Validiert Eingabe während der Benutzer tippt, um ungültige Werte zu verhindern + * Validates input as the user types to prevent invalid values */ validateBetInput(event: KeyboardEvent) { - // Erlaube Navigationstasten (Pfeile, Entf, Rücktaste, Tab) + // Allow navigation keys (arrows, delete, backspace, tab) const navigationKeys = ['ArrowLeft', 'ArrowRight', 'Delete', 'Backspace', 'Tab']; if (navigationKeys.includes(event.key)) { return; } - // Erlaube nur Zahlen + // Only allow numbers if (!/^\d$/.test(event.key)) { event.preventDefault(); return; } - // Ermittle den Wert, der nach dem Tastendruck entstehen würde + // Get the value that would result after the keypress const input = event.target as HTMLInputElement; const currentValue = input.value; const cursorPosition = input.selectionStart || 0; @@ -232,14 +230,14 @@ export default class CoinflipComponent implements OnInit { currentValue.substring(input.selectionEnd || cursorPosition); const numValue = Number(newValue); - // Verhindere Werte, die größer als das Guthaben sind + // Prevent values greater than balance if (numValue > this.balance()) { event.preventDefault(); } } - // Der Paste-Handler wurde der Einfachheit halber entfernt, da die updateBet-Methode - // jeden Wert behandelt, der in das Eingabefeld gelangt + // We removed the paste handler for simplicity since the updateBet method + // will handle any value that gets into the input field getResultClass() { if (!this.gameResult()) return '';