diff --git a/src/Koogle.Application/Games/ChristmasTree/ChristmasTreeGameLogicService.cs b/src/Koogle.Application/Games/ChristmasTree/ChristmasTreeGameLogicService.cs index 7f1cebb..305c95e 100644 --- a/src/Koogle.Application/Games/ChristmasTree/ChristmasTreeGameLogicService.cs +++ b/src/Koogle.Application/Games/ChristmasTree/ChristmasTreeGameLogicService.cs @@ -294,7 +294,8 @@ public class ChristmasTreeGameLogicService : IGameLogicService new TeamWonEvent { TeamName = winningTeam.Name, - PlayerIds = winningTeam.PlayerIds + PlayerIds = winningTeam.PlayerIds, + Message = "Baum fertig geschmückt!" } }; @@ -597,7 +598,8 @@ public class ChristmasTreeGameLogicService : IGameLogicService new TeamWonEvent { TeamName = winningTeam.Name, - PlayerIds = winningTeam.PlayerIds + PlayerIds = winningTeam.PlayerIds, + Message = "Baum fertig geschmückt!" } }; diff --git a/src/Koogle.Application/Games/DeathBox/DeathBoxGameLogicService.cs b/src/Koogle.Application/Games/DeathBox/DeathBoxGameLogicService.cs index 84b7ff8..ee77ec4 100644 --- a/src/Koogle.Application/Games/DeathBox/DeathBoxGameLogicService.cs +++ b/src/Koogle.Application/Games/DeathBox/DeathBoxGameLogicService.cs @@ -200,7 +200,8 @@ public class DeathBoxGameLogicService : IGameLogicService { PlayerId = model.PreviousPlayerId.Value, EliminationRank = eliminatedPlayers.Count, - RemainingPlayerCount = remainingPlayers + RemainingPlayerCount = remainingPlayers, + Message = "Sarg voll!" }); } } @@ -234,7 +235,8 @@ public class DeathBoxGameLogicService : IGameLogicService { PlayerId = playerId, EliminationRank = eliminatedPlayers.Count, - RemainingPlayerCount = remainingPlayers + RemainingPlayerCount = remainingPlayers, + Message = "Sarg voll!" }); } @@ -259,7 +261,8 @@ public class DeathBoxGameLogicService : IGameLogicService { gameEvents.Add(new PlayerWonEvent { - PlayerId = winnerId.Value + PlayerId = winnerId.Value, + Message = "Letzter Überlebender!" }); } } diff --git a/src/Koogle.Application/Games/FoxHunt/FoxHuntGameLogicService.cs b/src/Koogle.Application/Games/FoxHunt/FoxHuntGameLogicService.cs index 56ecf2e..2074e69 100644 --- a/src/Koogle.Application/Games/FoxHunt/FoxHuntGameLogicService.cs +++ b/src/Koogle.Application/Games/FoxHunt/FoxHuntGameLogicService.cs @@ -38,7 +38,7 @@ namespace Koogle.Application.Games.FoxHunt PlayerOrder = playerOrder, WinnerId = null, IsGameOver = false, - FoxCountLeft = playerStates.Count - 1 + FoxCountLeft = playerStates.Count }; return model; @@ -127,15 +127,30 @@ namespace Koogle.Application.Games.FoxHunt if (isGameOver) { - // looking for winner(s) - var maxLeading = playerStates.Values.Where(s => !s.FoxCaught) - .Select(s => s.PinCountFox - s.PinCountHunters).Max(); - foreach (var key in playerStates.Keys) + var escapedFoxes = playerStates.Where(kv => !kv.Value.FoxCaught).ToList(); + + if (escapedFoxes.Count == 0) { - if (playerStates[key].PinCountFox - playerStates[key].PinCountHunters == maxLeading) + // All foxes caught - no winner + gameEvents.Add(new GameEndedEvent { - playerStates[key].IsWinner = true; - gameEvents.Add(new PlayerWonEvent { PlayerId = key }); + WinnerId = null, + IsDraw = false, + Message = "Kein Sieger - alle Füchse wurden gefangen!" + }); + } + else + { + // looking for winner(s) among escaped foxes + var maxLeading = escapedFoxes + .Select(kv => kv.Value.PinCountFox - kv.Value.PinCountHunters).Max(); + foreach (var kv in escapedFoxes) + { + if (kv.Value.PinCountFox - kv.Value.PinCountHunters == maxLeading) + { + playerStates[kv.Key].IsWinner = true; + gameEvents.Add(new PlayerWonEvent { PlayerId = kv.Key, Message = "Bester Fuchs!" }); + } } } } diff --git a/src/Koogle.Application/Games/GameEvent.cs b/src/Koogle.Application/Games/GameEvent.cs index 1493b73..2caf89f 100644 --- a/src/Koogle.Application/Games/GameEvent.cs +++ b/src/Koogle.Application/Games/GameEvent.cs @@ -22,6 +22,11 @@ public abstract record GameEvent /// Timestamp when the event was created. /// public DateTime CreatedAt { get; init; } = DateTime.UtcNow; + + /// + /// Game-specific message to display in the UI. + /// + public string? Message { get; init; } } /// diff --git a/src/Koogle.Application/Games/Shit/ShitGameLogicService.cs b/src/Koogle.Application/Games/Shit/ShitGameLogicService.cs index 57f5d1f..912433b 100644 --- a/src/Koogle.Application/Games/Shit/ShitGameLogicService.cs +++ b/src/Koogle.Application/Games/Shit/ShitGameLogicService.cs @@ -104,7 +104,7 @@ public class ShitGameLogicService : IGameLogicService // Check for winner if (newPoints == 0) { - gameEvents.Add(new PlayerWonEvent { PlayerId = playerId }); + gameEvents.Add(new PlayerWonEvent { PlayerId = playerId, Message = "Auf Null gespielt!" }); model = model with { diff --git a/src/Koogle.Web/Components/Game/GameEventDialog.razor b/src/Koogle.Web/Components/Game/GameEventDialog.razor index b571d2f..45b4464 100644 --- a/src/Koogle.Web/Components/Game/GameEventDialog.razor +++ b/src/Koogle.Web/Components/Game/GameEventDialog.razor @@ -10,25 +10,43 @@ @if (!string.IsNullOrEmpty(WinnerName)) { @WinnerName hat gewonnen! + @if (!string.IsNullOrEmpty(WinnerMessage)) + { + @WinnerMessage + } } else if (!string.IsNullOrEmpty(WinningTeamName)) { Team @WinningTeamName hat gewonnen! + @if (!string.IsNullOrEmpty(WinningTeamMessage)) + { + @WinningTeamMessage + } } - @if (EliminatedNames.Count > 0) + @if (EliminatedPlayers.Count > 0) { } } - else if (EliminatedNames.Count > 0) + else if (!string.IsNullOrEmpty(GameEndedMessage)) + { + + Spiel beendet! + @GameEndedMessage + } + else if (EliminatedPlayers.Count > 0) { } - @foreach (var name in EliminatedNames) + @foreach (var player in EliminatedPlayers) { - @name ist ausgeschieden! + @player.Name ist ausgeschieden! + @if (!string.IsNullOrEmpty(player.Message)) + { + @player.Message + } } @@ -45,7 +63,7 @@ private IMudDialogInstance MudDialog { get; set; } = default!; [Parameter] - public List EliminatedNames { get; set; } = []; + public List<(string Name, string? Message)> EliminatedPlayers { get; set; } = []; [Parameter] public bool IsGameOver { get; set; } @@ -53,8 +71,17 @@ [Parameter] public string? WinnerName { get; set; } + [Parameter] + public string? WinnerMessage { get; set; } + [Parameter] public string? WinningTeamName { get; set; } + [Parameter] + public string? WinningTeamMessage { get; set; } + + [Parameter] + public string? GameEndedMessage { get; set; } + private void Close() => MudDialog.Close(DialogResult.Ok(true)); } diff --git a/src/Koogle.Web/Components/Game/GameEventDialogHost.razor b/src/Koogle.Web/Components/Game/GameEventDialogHost.razor index acbcd04..66a2dc8 100644 --- a/src/Koogle.Web/Components/Game/GameEventDialogHost.razor +++ b/src/Koogle.Web/Components/Game/GameEventDialogHost.razor @@ -44,28 +44,36 @@ _isShowingDialog = true; // Collect info from events - var eliminatedNames = new List(); + var eliminatedPlayers = new List<(string Name, string? Message)>(); string? winnerName = null; + string? winnerMessage = null; string? winningTeamName = null; + string? winningTeamMessage = null; + string? gameEndedMessage = null; foreach (var evt in newEvents) { switch (evt) { case PlayerEliminatedEvent eliminated: - eliminatedNames.Add(GetPlayerName(eliminated.PlayerId)); + eliminatedPlayers.Add((GetPlayerName(eliminated.PlayerId), eliminated.Message)); break; case PlayerWonEvent won: winnerName = GetPlayerName(won.PlayerId); + winnerMessage = won.Message; break; case TeamWonEvent teamWon: winningTeamName = teamWon.TeamName; + winningTeamMessage = teamWon.Message; + break; + case GameEndedEvent ended when ended.WinnerId == null && string.IsNullOrEmpty(ended.WinningTeamName): + gameEndedMessage = ended.Message ?? "Spiel beendet ohne Sieger"; break; } } // Only show dialog if there's something to show - if (eliminatedNames.Count == 0 && winnerName == null && winningTeamName == null) + if (eliminatedPlayers.Count == 0 && winnerName == null && winningTeamName == null && gameEndedMessage == null) { _isShowingDialog = false; return; @@ -73,10 +81,13 @@ var parameters = new DialogParameters { - { x => x.EliminatedNames, eliminatedNames }, + { x => x.EliminatedPlayers, eliminatedPlayers }, { x => x.IsGameOver, action.IsGameOver }, { x => x.WinnerName, winnerName }, - { x => x.WinningTeamName, winningTeamName } + { x => x.WinnerMessage, winnerMessage }, + { x => x.WinningTeamName, winningTeamName }, + { x => x.WinningTeamMessage, winningTeamMessage }, + { x => x.GameEndedMessage, gameEndedMessage } }; var options = new DialogOptions @@ -88,7 +99,7 @@ FullWidth = true }; - var title = winnerName != null || winningTeamName != null + var title = (action.IsGameOver && (winnerName != null || winningTeamName != null)) || gameEndedMessage != null ? "Spiel beendet!" : "Spieler ausgeschieden!";