fix foxhunt logic problems

extended GameEventDialog
This commit is contained in:
beo3000 2026-01-11 17:34:00 +01:00
parent 22f735f034
commit 6d672dd0c0
7 changed files with 88 additions and 25 deletions

View File

@ -294,7 +294,8 @@ public class ChristmasTreeGameLogicService : IGameLogicService
new TeamWonEvent new TeamWonEvent
{ {
TeamName = winningTeam.Name, TeamName = winningTeam.Name,
PlayerIds = winningTeam.PlayerIds PlayerIds = winningTeam.PlayerIds,
Message = "Baum fertig geschmückt!"
} }
}; };
@ -597,7 +598,8 @@ public class ChristmasTreeGameLogicService : IGameLogicService
new TeamWonEvent new TeamWonEvent
{ {
TeamName = winningTeam.Name, TeamName = winningTeam.Name,
PlayerIds = winningTeam.PlayerIds PlayerIds = winningTeam.PlayerIds,
Message = "Baum fertig geschmückt!"
} }
}; };

View File

@ -200,7 +200,8 @@ public class DeathBoxGameLogicService : IGameLogicService
{ {
PlayerId = model.PreviousPlayerId.Value, PlayerId = model.PreviousPlayerId.Value,
EliminationRank = eliminatedPlayers.Count, EliminationRank = eliminatedPlayers.Count,
RemainingPlayerCount = remainingPlayers RemainingPlayerCount = remainingPlayers,
Message = "Sarg voll!"
}); });
} }
} }
@ -234,7 +235,8 @@ public class DeathBoxGameLogicService : IGameLogicService
{ {
PlayerId = playerId, PlayerId = playerId,
EliminationRank = eliminatedPlayers.Count, EliminationRank = eliminatedPlayers.Count,
RemainingPlayerCount = remainingPlayers RemainingPlayerCount = remainingPlayers,
Message = "Sarg voll!"
}); });
} }
@ -259,7 +261,8 @@ public class DeathBoxGameLogicService : IGameLogicService
{ {
gameEvents.Add(new PlayerWonEvent gameEvents.Add(new PlayerWonEvent
{ {
PlayerId = winnerId.Value PlayerId = winnerId.Value,
Message = "Letzter Überlebender!"
}); });
} }
} }

View File

@ -38,7 +38,7 @@ namespace Koogle.Application.Games.FoxHunt
PlayerOrder = playerOrder, PlayerOrder = playerOrder,
WinnerId = null, WinnerId = null,
IsGameOver = false, IsGameOver = false,
FoxCountLeft = playerStates.Count - 1 FoxCountLeft = playerStates.Count
}; };
return model; return model;
@ -127,15 +127,30 @@ namespace Koogle.Application.Games.FoxHunt
if (isGameOver) if (isGameOver)
{ {
// looking for winner(s) var escapedFoxes = playerStates.Where(kv => !kv.Value.FoxCaught).ToList();
var maxLeading = playerStates.Values.Where(s => !s.FoxCaught)
.Select(s => s.PinCountFox - s.PinCountHunters).Max(); if (escapedFoxes.Count == 0)
foreach (var key in playerStates.Keys)
{ {
if (playerStates[key].PinCountFox - playerStates[key].PinCountHunters == maxLeading) // All foxes caught - no winner
gameEvents.Add(new GameEndedEvent
{ {
playerStates[key].IsWinner = true; WinnerId = null,
gameEvents.Add(new PlayerWonEvent { PlayerId = key }); 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!" });
}
} }
} }
} }

View File

@ -22,6 +22,11 @@ public abstract record GameEvent
/// Timestamp when the event was created. /// Timestamp when the event was created.
/// </summary> /// </summary>
public DateTime CreatedAt { get; init; } = DateTime.UtcNow; public DateTime CreatedAt { get; init; } = DateTime.UtcNow;
/// <summary>
/// Game-specific message to display in the UI.
/// </summary>
public string? Message { get; init; }
} }
/// <summary> /// <summary>

View File

@ -104,7 +104,7 @@ public class ShitGameLogicService : IGameLogicService
// Check for winner // Check for winner
if (newPoints == 0) if (newPoints == 0)
{ {
gameEvents.Add(new PlayerWonEvent { PlayerId = playerId }); gameEvents.Add(new PlayerWonEvent { PlayerId = playerId, Message = "Auf Null gespielt!" });
model = model with model = model with
{ {

View File

@ -10,25 +10,43 @@
@if (!string.IsNullOrEmpty(WinnerName)) @if (!string.IsNullOrEmpty(WinnerName))
{ {
<MudText Typo="Typo.h5">@WinnerName hat gewonnen!</MudText> <MudText Typo="Typo.h5">@WinnerName hat gewonnen!</MudText>
@if (!string.IsNullOrEmpty(WinnerMessage))
{
<MudText Typo="Typo.body1" Color="Color.Success">@WinnerMessage</MudText>
}
} }
else if (!string.IsNullOrEmpty(WinningTeamName)) else if (!string.IsNullOrEmpty(WinningTeamName))
{ {
<MudText Typo="Typo.h5">Team @WinningTeamName hat gewonnen!</MudText> <MudText Typo="Typo.h5">Team @WinningTeamName hat gewonnen!</MudText>
@if (!string.IsNullOrEmpty(WinningTeamMessage))
{
<MudText Typo="Typo.body1" Color="Color.Success">@WinningTeamMessage</MudText>
}
} }
@if (EliminatedNames.Count > 0) @if (EliminatedPlayers.Count > 0)
{ {
<MudDivider Class="my-2" /> <MudDivider Class="my-2" />
} }
} }
else if (EliminatedNames.Count > 0) else if (!string.IsNullOrEmpty(GameEndedMessage))
{
<MudIcon Icon="@Icons.Material.Filled.SportsScore" Color="Color.Warning" Size="Size.Large" Style="font-size: 4rem;" />
<MudText Typo="Typo.h4" Color="Color.Warning">Spiel beendet!</MudText>
<MudText Typo="Typo.h5">@GameEndedMessage</MudText>
}
else if (EliminatedPlayers.Count > 0)
{ {
<MudIcon Icon="@Icons.Material.Filled.PersonOff" Color="Color.Error" Size="Size.Large" Style="font-size: 4rem;" /> <MudIcon Icon="@Icons.Material.Filled.PersonOff" Color="Color.Error" Size="Size.Large" Style="font-size: 4rem;" />
} }
@foreach (var name in EliminatedNames) @foreach (var player in EliminatedPlayers)
{ {
<MudAlert Severity="Severity.Error" Variant="Variant.Filled" Dense="false"> <MudAlert Severity="Severity.Error" Variant="Variant.Filled" Dense="false">
<MudText Typo="Typo.h6">@name ist ausgeschieden!</MudText> <MudText Typo="Typo.h6">@player.Name ist ausgeschieden!</MudText>
@if (!string.IsNullOrEmpty(player.Message))
{
<MudText Typo="Typo.body2">@player.Message</MudText>
}
</MudAlert> </MudAlert>
} }
</MudStack> </MudStack>
@ -45,7 +63,7 @@
private IMudDialogInstance MudDialog { get; set; } = default!; private IMudDialogInstance MudDialog { get; set; } = default!;
[Parameter] [Parameter]
public List<string> EliminatedNames { get; set; } = []; public List<(string Name, string? Message)> EliminatedPlayers { get; set; } = [];
[Parameter] [Parameter]
public bool IsGameOver { get; set; } public bool IsGameOver { get; set; }
@ -53,8 +71,17 @@
[Parameter] [Parameter]
public string? WinnerName { get; set; } public string? WinnerName { get; set; }
[Parameter]
public string? WinnerMessage { get; set; }
[Parameter] [Parameter]
public string? WinningTeamName { get; set; } 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)); private void Close() => MudDialog.Close(DialogResult.Ok(true));
} }

View File

@ -44,28 +44,36 @@
_isShowingDialog = true; _isShowingDialog = true;
// Collect info from events // Collect info from events
var eliminatedNames = new List<string>(); var eliminatedPlayers = new List<(string Name, string? Message)>();
string? winnerName = null; string? winnerName = null;
string? winnerMessage = null;
string? winningTeamName = null; string? winningTeamName = null;
string? winningTeamMessage = null;
string? gameEndedMessage = null;
foreach (var evt in newEvents) foreach (var evt in newEvents)
{ {
switch (evt) switch (evt)
{ {
case PlayerEliminatedEvent eliminated: case PlayerEliminatedEvent eliminated:
eliminatedNames.Add(GetPlayerName(eliminated.PlayerId)); eliminatedPlayers.Add((GetPlayerName(eliminated.PlayerId), eliminated.Message));
break; break;
case PlayerWonEvent won: case PlayerWonEvent won:
winnerName = GetPlayerName(won.PlayerId); winnerName = GetPlayerName(won.PlayerId);
winnerMessage = won.Message;
break; break;
case TeamWonEvent teamWon: case TeamWonEvent teamWon:
winningTeamName = teamWon.TeamName; 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; break;
} }
} }
// Only show dialog if there's something to show // 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; _isShowingDialog = false;
return; return;
@ -73,10 +81,13 @@
var parameters = new DialogParameters<GameEventDialog> var parameters = new DialogParameters<GameEventDialog>
{ {
{ x => x.EliminatedNames, eliminatedNames }, { x => x.EliminatedPlayers, eliminatedPlayers },
{ x => x.IsGameOver, action.IsGameOver }, { x => x.IsGameOver, action.IsGameOver },
{ x => x.WinnerName, winnerName }, { 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 var options = new DialogOptions
@ -88,7 +99,7 @@
FullWidth = true FullWidth = true
}; };
var title = winnerName != null || winningTeamName != null var title = (action.IsGameOver && (winnerName != null || winningTeamName != null)) || gameEndedMessage != null
? "Spiel beendet!" ? "Spiel beendet!"
: "Spieler ausgeschieden!"; : "Spieler ausgeschieden!";