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
{
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!"
}
};

View File

@ -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!"
});
}
}

View File

@ -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!" });
}
}
}
}

View File

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

View File

@ -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
{

View File

@ -10,25 +10,43 @@
@if (!string.IsNullOrEmpty(WinnerName))
{
<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))
{
<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" />
}
}
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;" />
}
@foreach (var name in EliminatedNames)
@foreach (var player in EliminatedPlayers)
{
<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>
}
</MudStack>
@ -45,7 +63,7 @@
private IMudDialogInstance MudDialog { get; set; } = default!;
[Parameter]
public List<string> 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));
}

View File

@ -44,28 +44,36 @@
_isShowingDialog = true;
// Collect info from events
var eliminatedNames = new List<string>();
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<GameEventDialog>
{
{ 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!";