-
Spieler: {{ player.score }} @for (opponent of opponents; track opponent; let i = $index) { | Gegner {{ i + 1 }}: {{ opponent.score }} } | Runde: {{ currentRound }}/10
+
@@ -42,10 +56,18 @@
-
- | {{ stat.round }} |
- {{ stat.playerStitches }} |
- {{ stitches }} |
+
+ | {{ stat.round }} |
+
+ {{ roundPredictions[stat.round - 1]?.playerPrediction === null ? '-' : roundPredictions[stat.round - 1]?.playerPrediction }}/{{ stat.playerStitches }}
+ {{ player.score }}
+ |
+ @for(opponentTip of roundPredictions[stat.round - 1]?.opponentPredictions; track opponentTip; let j = $index){
+
+ {{ opponentTip === null ? '-' : opponentTip }}/{{ stat.opponentStitches[j] }}
+ {{ opponents[j].score }}
+ |
+ }
diff --git a/src/app/game.component.scss b/src/app/game.component.scss
index 4cefe92..fb10036 100644
--- a/src/app/game.component.scss
+++ b/src/app/game.component.scss
@@ -15,13 +15,14 @@
}
.opponents-area {
display: flex;
- justify-content: space-around;
+ justify-content: center;
min-height: 320px;
}
.opponent-hand {
position: relative;
width: 200px;
height: 280px;
+ margin-right: 150px;
}
.stacked-card {
position: absolute;
@@ -83,12 +84,14 @@
font-size: 14px;
z-index: 100;
text-align: center;
+ border-collapse: collapse;
+ text-align: center;
}
.round-stats th,
.round-stats td {
- padding: 8px;
- border-bottom: 1px solid #ddd;
+ padding: 5px;
+ border: 1px solid #ddd;
}
.round-stats thead {
@@ -99,3 +102,51 @@
.round-stats tbody tr:last-child td {
border-bottom: none;
}
+.tip-value {
+ font-size: 12px;
+ vertical-align: top;
+ display: block;
+}
+
+.stitch-value {
+ font-size: 24px;
+ font-weight: bold;
+ display: block;
+}
+.round-value {
+ font-size: 24px;
+ font-weight: bold;
+}
+.tip-phase {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+ background-color: #f9f9f9;
+ border: 1px solid #ccc;
+ padding: 10px;
+ border-radius: 8px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ z-index: 100;
+}
+
+.tip-phase input {
+ width: 60px;
+ height: 30px;
+ border: 2px solid #ccc;
+ border-radius: 5px;
+ text-align: center;
+ margin-bottom: 10px;
+}
+
+.tip-phase input.active {
+ border-color: red;
+ box-shadow: 0 0 10px red;
+}
+td.alreadyTipped {
+ border-color: blue;
+ box-shadow: 0 0 10px blue;
+}
+.tip-phase label {
+ margin-right: 10px;
+ font-weight: bold;
+}
diff --git a/src/app/game.component.ts b/src/app/game.component.ts
index 29d7200..5f6e111 100644
--- a/src/app/game.component.ts
+++ b/src/app/game.component.ts
@@ -1,9 +1,9 @@
-import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
+import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
-import { CardFrontComponent } from './card-front.component';
import { CardBackComponent } from './card-back.component';
-import { CardService, Card } from './card.service';
+import { CardFrontComponent } from './card-front.component';
+import { Card, CardService } from './card.service';
import { GameRuleEngine } from './game-rule-engine';
export interface Player {
@@ -17,12 +17,16 @@ interface RoundStats {
playerStitches: number;
opponentStitches: number[];
}
+interface RoundPrediction {
+ playerPrediction: number | null;
+ opponentPredictions: Array
;
+}
@Component({
selector: 'app-game',
standalone: true,
imports: [CommonModule, FormsModule, CardFrontComponent, CardBackComponent],
templateUrl: './game.component.html',
- styleUrls: ['./game.component.scss']
+ styleUrls: ['./game.component.scss'],
})
export class GameComponent implements OnInit {
player: Player = { id: 0, hand: [], playedCard: null, score: 0 };
@@ -36,17 +40,24 @@ export class GameComponent implements OnInit {
roundStats: RoundStats[] = [];
private ruleEngine: GameRuleEngine;
+ roundPredictions: RoundPrediction[] = [];
+ currentTipPlayerIndex: number = 0;
+ isTipPhase: boolean = true;
+ numberTips = 0;
constructor(private cardService: CardService) {
this.ruleEngine = new GameRuleEngine(cardService);
}
- ngOnInit() {}
+ ngOnInit() {
+ this.startGame();
+ }
startGame() {
- if (this.numberOfOpponents < 1 || this.numberOfOpponents > 3) {
- alert("Bitte wählen Sie 1 bis 3 Gegner.");
- return;
- }
+ // if (this.numberOfOpponents < 1 || this.numberOfOpponents > 3) {
+ // alert('Bitte wählen Sie 1 bis 3 Gegner.');
+ // return;
+ // }
+ this.numberOfOpponents = 2;
this.gameStarted = true;
this.initializePlayers();
this.startNewRound();
@@ -75,8 +86,74 @@ export class GameComponent implements OnInit {
});
this.resetPlayedCards();
- this.currentPlayerIndex = this.ruleEngine.determineStartingPlayer(this.currentRound, this.opponents.length + 1);
- this.playTrick();
+
+ // Runde für roundStats initialisieren
+ if (!this.roundStats[this.currentRound - 1]) {
+ this.roundStats[this.currentRound - 1] = {
+ round: this.currentRound,
+ playerStitches: 0,
+ opponentStitches: new Array(this.opponents.length).fill(0),
+ };
+ }
+
+ // Tipp-Phase initialisieren
+ this.isTipPhase = true;
+ this.currentTipPlayerIndex = (this.currentRound - 1) % (this.opponents.length + 1);
+ this.initializeTipPhase();
+ }
+ initializeTipPhase() {
+ // Initialisiere die Vorhersagen für die Runde
+ this.roundPredictions[this.currentRound - 1] = {
+ playerPrediction: null,
+ opponentPredictions: new Array(this.opponents.length).fill(null),
+ };
+
+ // Starte das Tippen beim richtigen Spieler basierend auf der Runde
+ this.currentTipPlayerIndex = (this.currentRound - 1) % (this.opponents.length + 1);
+ this.numberTips = 0;
+ // Wenn der aktuelle Spieler kein menschlicher Spieler ist, den ersten Gegner automatisch tippen lassen
+ if (this.currentTipPlayerIndex > 0) {
+ this.submitOpponentTip(this.currentTipPlayerIndex - 1);
+ }
+ }
+
+ submitOpponentTip(index: number) {
+ const randomTip = Math.floor(Math.random() * this.getCardsForRound(this.currentRound));
+ this.roundPredictions[this.currentRound - 1].opponentPredictions[index] = randomTip;
+
+ this.numberTips++;
+ if (this.numberTips === this.opponents.length + 1) {
+ // Alle haben getippt, beende die Tippphase
+ this.isTipPhase = false;
+ this.playTrick();
+ } else if ((this.currentTipPlayerIndex + 1) % 3 === 0) {
+ // Spieler ist jetzt dran
+ this.currentTipPlayerIndex = 0;
+ return;
+ } else {
+ // Nächster Gegner ist dran
+ this.currentTipPlayerIndex++;
+ setTimeout(() => this.submitOpponentTip(this.currentTipPlayerIndex - 1), 1000);
+ }
+ }
+
+ submitPlayerTip() {
+ const playerPrediction = this.roundPredictions[this.currentRound - 1]?.playerPrediction;
+ if (playerPrediction === null || playerPrediction < 0 || playerPrediction > this.getCardsForRound(this.currentRound)) {
+ return; // Ungültiger Tipp oder noch nicht gesetzt
+ }
+
+ // Spieler hat getippt, wechsle zum nächsten Spieler
+ this.currentTipPlayerIndex++;
+ this.numberTips++;
+ if (this.numberTips === this.opponents.length + 1) {
+ // Alle haben getippt, beende die Tippphase
+ this.isTipPhase = false;
+ this.playTrick();
+ } else {
+ // Der nächste Gegner ist an der Reihe
+ setTimeout(() => this.submitOpponentTip(0), 1000);
+ }
}
playTrick() {
@@ -135,8 +212,8 @@ export class GameComponent implements OnInit {
const allPlayers = [this.player, ...this.opponents];
const winner = this.ruleEngine.determineWinner(this.playedCards, allPlayers);
winner.score++;
-
- // Neue Logik, um Stiche zu speichern
+
+ // Stiche in den roundStats aktualisieren
if (!this.roundStats[this.currentRound - 1]) {
this.roundStats[this.currentRound - 1] = {
round: this.currentRound,
@@ -144,15 +221,29 @@ export class GameComponent implements OnInit {
opponentStitches: new Array(this.opponents.length).fill(0),
};
}
-
+
if (winner === this.player) {
this.roundStats[this.currentRound - 1].playerStitches++;
} else {
const opponentIndex = this.opponents.indexOf(winner);
this.roundStats[this.currentRound - 1].opponentStitches[opponentIndex]++;
}
-
+
+ // Überprüfe, ob die Runde vorbei ist
if (this.player.hand.length === 0) {
+ // Tipp-Prüfung und Extrapunkte
+ const predictions = this.roundPredictions[this.currentRound - 1];
+ if (predictions.playerPrediction === this.roundStats[this.currentRound - 1].playerStitches) {
+ this.player.score += 10; // Extrapunkte für richtigen Tipp
+ }
+
+ this.opponents.forEach((opponent, index) => {
+ if (predictions.opponentPredictions[index] === this.roundStats[this.currentRound - 1].opponentStitches[index]) {
+ opponent.score += 10; // Extrapunkte für richtigen Tipp
+ }
+ });
+
+ // Neue Runde starten oder Spiel beenden
if (this.currentRound < 10) {
setTimeout(() => this.startNewRound(), 500);
} else {
@@ -169,7 +260,7 @@ export class GameComponent implements OnInit {
this.playedCards = [];
this.leadCard = null;
this.player.playedCard = null;
- this.opponents.forEach(opponent => opponent.playedCard = null);
+ this.opponents.forEach(opponent => (opponent.playedCard = null));
}
getCardsForRound(round: number): number {
@@ -182,12 +273,10 @@ export class GameComponent implements OnInit {
const maxScore = Math.max(...allPlayers.map(p => p.score));
const winners = allPlayers.filter(p => p.score === maxScore);
- let result = winners.length > 1 ? "Unentschieden!" :
- winners[0] === this.player ? "Sie haben gewonnen!" :
- `Gegner ${winners[0].id} hat gewonnen!`;
+ let result = winners.length > 1 ? 'Unentschieden!' : winners[0] === this.player ? 'Sie haben gewonnen!' : `Gegner ${winners[0].id} hat gewonnen!`;
let scoreMessage = `Endstand - Spieler: ${this.player.score}`;
- this.opponents.forEach((opponent) => {
+ this.opponents.forEach(opponent => {
scoreMessage += `, Gegner ${opponent.id}: ${opponent.score}`;
});
@@ -196,4 +285,7 @@ export class GameComponent implements OnInit {
this.currentRound = 0;
this.player.score = 0;
}
-}
\ No newline at end of file
+ tipAlreadySet(value: number | null | undefined) {
+ return value !== null;
+ }
+}