Compare commits

..

No commits in common. "c24923950770b7b2cba9659feb029dbf0ec7743f" and "4dbc81bef249fffefbf6efc5290e8d46a488e4cc" have entirely different histories.

9 changed files with 14 additions and 71 deletions

View File

@ -122,21 +122,6 @@ namespace GoodWood.Application.Games.FoxHunt
var nextPlayerId = GetNextId(model, chooseNextFox); var nextPlayerId = GetNextId(model, chooseNextFox);
if (chooseNextFox)
{
gameEvents.Add(new FoxChangedEvent
{
FoxPlayerId = foxId,
FoxEscaped = playerStates[foxId].FoxEscaped,
NextFoxPlayerId = nextPlayerId,
Message = playerStates[foxId].FoxEscaped
? "Fuchs entkommen! Nächster Fuchs ist dran."
: "Fuchs gefangen! Nächster Fuchs ist dran."
});
}
// Check GAME END // Check GAME END
var isGameOver = model.FoxCountLeft == 0; var isGameOver = model.FoxCountLeft == 0;

View File

@ -35,8 +35,7 @@ namespace GoodWood.Application.Games.FoxHunt
ThrowMode = throwMode, ThrowMode = throwMode,
ThrowsPerRound = throwsPerRound, ThrowsPerRound = throwsPerRound,
ParticipantsMode = participantsMode, ParticipantsMode = participantsMode,
LeadingThrows = leadingThrows, LeadingThrows = leadingThrows
PinCountGoal = pinCountGoal
}; };
} }
} }

View File

@ -11,7 +11,6 @@ namespace GoodWood.Application.Games;
[JsonDerivedType(typeof(PlayerWonEvent), "PlayerWon")] [JsonDerivedType(typeof(PlayerWonEvent), "PlayerWon")]
[JsonDerivedType(typeof(TeamWonEvent), "TeamWon")] [JsonDerivedType(typeof(TeamWonEvent), "TeamWon")]
[JsonDerivedType(typeof(GameEndedEvent), "GameEnded")] [JsonDerivedType(typeof(GameEndedEvent), "GameEnded")]
[JsonDerivedType(typeof(FoxChangedEvent), "FoxChanged")]
public abstract record GameEvent public abstract record GameEvent
{ {
/// <summary> /// <summary>
@ -78,27 +77,6 @@ public record TeamWonEvent : GameEvent
public required IReadOnlyList<Guid> PlayerIds { get; init; } public required IReadOnlyList<Guid> PlayerIds { get; init; }
} }
/// <summary>
/// Event when the fox role changes (fox escaped or was caught).
/// </summary>
public record FoxChangedEvent : GameEvent
{
/// <summary>
/// ID of the player who was fox.
/// </summary>
public required Guid FoxPlayerId { get; init; }
/// <summary>
/// True if the fox escaped, false if caught by hunters.
/// </summary>
public bool FoxEscaped { get; init; }
/// <summary>
/// ID of the next fox (null if game is over).
/// </summary>
public Guid? NextFoxPlayerId { get; init; }
}
/// <summary> /// <summary>
/// Event when the game ends (covers any end scenario). /// Event when the game ends (covers any end scenario).
/// </summary> /// </summary>

View File

@ -377,22 +377,21 @@ public class DayService : IDayService
if (club.ExpenseCalculation == ExpenseCalculation.None) if (club.ExpenseCalculation == ExpenseCalculation.None)
return; return;
// 3. Get total expenses per participant for this day // 3. Get all PersonExpense prices for this day
var personExpenseTotals = await context.PersonExpenses var dayExpensePrices = await context.PersonExpenses
.Where(pe => pe.DayId == dayId && !pe.IsDeleted) .Where(pe => pe.DayId == dayId && !pe.IsDeleted)
.GroupBy(pe => pe.PersonId) .Select(pe => pe.Price)
.Select(g => g.Sum(pe => pe.Price))
.ToListAsync(ct); .ToListAsync(ct);
// 4. Edge case: No expenses - skip // 4. Edge case: No expenses - skip
if (personExpenseTotals.Count == 0) if (dayExpensePrices.Count == 0)
return; return;
// 5. Calculate price based on per-person totals // 5. Calculate price
decimal calculatedPrice = club.ExpenseCalculation switch decimal calculatedPrice = club.ExpenseCalculation switch
{ {
ExpenseCalculation.Average => Math.Round(personExpenseTotals.Average(), 2), ExpenseCalculation.Average => Math.Round(dayExpensePrices.Average(), 2),
ExpenseCalculation.Maximum => personExpenseTotals.Max(), ExpenseCalculation.Maximum => dayExpensePrices.Max(),
_ => 0m _ => 0m
}; };

View File

@ -109,7 +109,6 @@
var setup = new FoxHuntGameSetup var setup = new FoxHuntGameSetup
{ {
LeadingThrows = _options.LeadingThrows, LeadingThrows = _options.LeadingThrows,
PinCountGoal = _options.PinCountGoal,
ParticipantsMode = _options.ParticipantsMode ParticipantsMode = _options.ParticipantsMode
}; };
await OnOptionsChanged.InvokeAsync(setup); await OnOptionsChanged.InvokeAsync(setup);

View File

@ -34,11 +34,6 @@
<MudText Typo="Typo.h4" Color="Color.Warning">Spiel beendet!</MudText> <MudText Typo="Typo.h4" Color="Color.Warning">Spiel beendet!</MudText>
<MudText Typo="Typo.h5">@GameEndedMessage</MudText> <MudText Typo="Typo.h5">@GameEndedMessage</MudText>
} }
else if (!string.IsNullOrEmpty(FoxChangedMessage))
{
<MudIcon Icon="@Icons.Material.Filled.Pets" Color="Color.Info" Size="Size.Large" Style="font-size: 4rem;" />
<MudText Typo="Typo.h5">@FoxChangedMessage</MudText>
}
else if (EliminatedPlayers.Count > 0) 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;" />
@ -88,8 +83,5 @@
[Parameter] [Parameter]
public string? GameEndedMessage { get; set; } public string? GameEndedMessage { get; set; }
[Parameter]
public string? FoxChangedMessage { get; set; }
private void Close() => MudDialog.Close(DialogResult.Ok(true)); private void Close() => MudDialog.Close(DialogResult.Ok(true));
} }

View File

@ -50,7 +50,6 @@
string? winningTeamName = null; string? winningTeamName = null;
string? winningTeamMessage = null; string? winningTeamMessage = null;
string? gameEndedMessage = null; string? gameEndedMessage = null;
string? foxChangedMessage = null;
foreach (var evt in newEvents) foreach (var evt in newEvents)
{ {
@ -70,14 +69,11 @@
case GameEndedEvent ended when ended.WinnerId == null && string.IsNullOrEmpty(ended.WinningTeamName): case GameEndedEvent ended when ended.WinnerId == null && string.IsNullOrEmpty(ended.WinningTeamName):
gameEndedMessage = ended.Message ?? "Spiel beendet ohne Sieger"; gameEndedMessage = ended.Message ?? "Spiel beendet ohne Sieger";
break; break;
case FoxChangedEvent foxChanged:
foxChangedMessage = foxChanged.Message;
break;
} }
} }
// Only show dialog if there's something to show // Only show dialog if there's something to show
if (eliminatedPlayers.Count == 0 && winnerName == null && winningTeamName == null && gameEndedMessage == null && foxChangedMessage == null) if (eliminatedPlayers.Count == 0 && winnerName == null && winningTeamName == null && gameEndedMessage == null)
{ {
_isShowingDialog = false; _isShowingDialog = false;
return; return;
@ -91,8 +87,7 @@
{ x => x.WinnerMessage, winnerMessage }, { x => x.WinnerMessage, winnerMessage },
{ x => x.WinningTeamName, winningTeamName }, { x => x.WinningTeamName, winningTeamName },
{ x => x.WinningTeamMessage, winningTeamMessage }, { x => x.WinningTeamMessage, winningTeamMessage },
{ x => x.GameEndedMessage, gameEndedMessage }, { x => x.GameEndedMessage, gameEndedMessage }
{ x => x.FoxChangedMessage, foxChangedMessage }
}; };
var options = new DialogOptions var options = new DialogOptions
@ -106,9 +101,7 @@
var title = (action.IsGameOver && (winnerName != null || winningTeamName != null)) || gameEndedMessage != null var title = (action.IsGameOver && (winnerName != null || winningTeamName != null)) || gameEndedMessage != null
? "Spiel beendet!" ? "Spiel beendet!"
: foxChangedMessage != null : "Spieler ausgeschieden!";
? "Fuchswechsel!"
: "Spieler ausgeschieden!";
await InvokeAsync(async () => await InvokeAsync(async () =>
{ {

View File

@ -1,7 +1,7 @@
@using GoodWood.Domain.Enums @using GoodWood.Domain.Enums
<div class="pin @GetPinClass()" @onclick="OnClick" style="@GetStyle()"> <div class="pin @GetPinClass()" @onclick="OnClick" style="@GetStyle()">
<span class="pin-number"></span> <span class="pin-number">@PinNumber</span>
</div> </div>
<style> <style>

View File

@ -30,15 +30,13 @@
<MudSelect T="int" @bind-Value="_selectedMonth" Label="Monat" Style="width: 150px;"> <MudSelect T="int" @bind-Value="_selectedMonth" Label="Monat" Style="width: 150px;">
@for (int m = 1; m <= 12; m++) @for (int m = 1; m <= 12; m++)
{ {
var month = m; <MudSelectItem Value="@m">@GetMonthName(m)</MudSelectItem>
<MudSelectItem Value="@month">@GetMonthName(month)</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect T="int" @bind-Value="_selectedYear" Label="Jahr" Style="width: 120px;"> <MudSelect T="int" @bind-Value="_selectedYear" Label="Jahr" Style="width: 120px;">
@for (int y = DateTime.Today.Year; y >= DateTime.Today.Year - 5; y--) @for (int y = DateTime.Today.Year; y >= DateTime.Today.Year - 5; y--)
{ {
var year = y; <MudSelectItem Value="@y">@y</MudSelectItem>
<MudSelectItem Value="@year">@year</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Refresh" <MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Refresh"