KoogleApp/src/Koogle.Web/Components/Game/Shit/ShitBoard.razor

271 lines
8.9 KiB
Plaintext

@using Fluxor
@using Koogle.Application.DTOs
@using Koogle.Application.Games
@using Koogle.Application.Games.Shit
@using Koogle.Web.Store.GameState
@using Koogle.Web.Store.DayState
@using MudBlazor
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@implements IDisposable
@inject IState<GameState> GameState
@inject IState<DayState> DayState
<MudPaper Class="pa-4">
@* <MudText Typo="Typo.h6" Class="mb-4">
<MudIcon Icon="@Icons.Material.Filled.TableChart" Class="mr-2" />
Scheiss-Spiel - Tafel
</MudText> *@
@if (_model == null)
{
<MudAlert Severity="Severity.Info">
Spiel noch nicht gestartet.
</MudAlert>
}
else
{
@* Game info header *@
<MudPaper Class="pa-3 mb-4" Elevation="0" Style="background-color: var(--mud-palette-background-grey);">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<MudText Typo="Typo.body1">
<strong>Scheiss-Zahl:</strong>
<MudChip T="string" Size="Size.Small" Color="Color.Error" Variant="Variant.Filled">
@_model.ShitNumber
</MudChip>
</MudText>
<MudText Typo="Typo.body1">
<strong>Gesammelte Punkte:</strong>
@if (_model.CollectedPoints > 0)
{
<MudChip T="string" Size="Size.Small" Color="Color.Warning" Variant="Variant.Filled">
@_model.CollectedPoints
</MudChip>
}
else
{
<span>0</span>
}
</MudText>
</MudStack>
</MudPaper>
@* Last throw info *@
@if (_model.LastThrowPins.HasValue)
{
<MudAlert Severity="@GetLastThrowSeverity()" Class="mb-4" Dense="true">
@if (_model.LastThrowWasShitNumber)
{
<span>Scheiss-Zahl getroffen! Du bekommst alle gesammelten Punkte.</span>
}
else if (_model.LastThrowWasGutter)
{
<span>Rinne! Du bekommst alle gesammelten Punkte.</span>
}
else
{
<span>@_model.LastThrowPins Kegel - @_model.LastThrowPins Punkte abgezogen.</span>
}
</MudAlert>
}
@* Winner announcement *@
@if (_model.IsGameOver && _model.WinnerId.HasValue)
{
var winnerName = GetPlayerName(_model.WinnerId.Value);
<MudAlert Severity="Severity.Success" Class="mb-4">
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
<MudIcon Icon="@Icons.Material.Filled.EmojiEvents" />
<MudText Typo="Typo.h6">@winnerName hat gewonnen!</MudText>
</MudStack>
</MudAlert>
}
@* Players table *@
<MudTable Items="@_playerStats"
Dense="true"
Hover="true"
Striped="true"
Bordered="true"
Class="mb-4">
<HeaderContent>
<MudTh>Spieler</MudTh>
<MudTh Style="text-align: right">Punkte</MudTh>
<MudTh Style="text-align: center">Status</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>
@if (context.IsCurrentPlayer && !_model.IsGameOver)
{
<MudBadge Color="Color.Primary" Dot="true" Overlap="true">
<MudText Typo="Typo.body1" Style="font-weight: 600">
@context.PlayerName
</MudText>
</MudBadge>
}
else
{
<MudText Typo="Typo.body1">@context.PlayerName</MudText>
}
</MudTd>
<MudTd Style="text-align: right">
<MudText Typo="Typo.h6" Style="@GetPointsStyle(context)">
@context.Points
</MudText>
</MudTd>
<MudTd Style="text-align: center">
@if (context.IsWinner)
{
<MudChip T="string" Size="Size.Small" Color="Color.Success" Variant="Variant.Filled"
Icon="@Icons.Material.Filled.EmojiEvents">
GEWINNER
</MudChip>
}
else if (_model.IsGameOver)
{
<MudChip T="string" Size="Size.Small" Color="Color.Error" Variant="Variant.Outlined"
Icon="@Icons.Material.Filled.MoneyOff">
-@context.Points Strafe
</MudChip>
}
else if (context.IsCurrentPlayer)
{
<MudChip T="string" Size="Size.Small" Color="Color.Primary" Variant="Variant.Outlined">
Am Zug
</MudChip>
}
</MudTd>
</RowTemplate>
</MudTable>
@* Progress indicator *@
@if (!_model.IsGameOver)
{
<MudPaper Class="pa-3" Elevation="0" Style="background-color: var(--mud-palette-background-grey);">
<MudText Typo="Typo.body2" Color="Color.Secondary">
Wer zuerst 0 Punkte erreicht, gewinnt!
</MudText>
</MudPaper>
}
}
</MudPaper>
@code {
private ShitGameModel? _model;
private List<PlayerStatsRow> _playerStats = [];
protected override void OnInitialized()
{
base.OnInitialized();
GameState.StateChanged += OnGameStateChanged;
UpdateStats();
}
private void OnGameStateChanged(object? sender, EventArgs e)
{
UpdateStats();
InvokeAsync(StateHasChanged);
}
private void UpdateStats()
{
_playerStats.Clear();
_model = null;
var gameState = GameState.Value;
if (gameState.GameModel is ShitGameModel model)
{
_model = model;
}
else if (gameState.GameModel is System.Text.Json.JsonElement jsonElement)
{
try
{
_model = System.Text.Json.JsonSerializer.Deserialize<ShitGameModel>(
jsonElement.GetRawText(),
GameModelFactory.JsonSerializerOptions);
}
catch
{
return;
}
}
if (_model?.PlayerPoints == null)
{
return;
}
var currentPlayerId = gameState.Participants.CurrentPlayerId;
var persons = DayState.Value.AvailablePersons;
foreach (var (playerId, points) in _model.PlayerPoints)
{
var person = persons.FirstOrDefault(p => p.Id == playerId);
var playerName = person?.Name ?? "Unbekannt";
_playerStats.Add(new PlayerStatsRow
{
PlayerId = playerId,
PlayerName = playerName,
Points = points,
IsWinner = _model.WinnerId == playerId,
IsCurrentPlayer = playerId == currentPlayerId
});
}
// Sort: Winner first, then by points ascending (lowest is best)
_playerStats = _playerStats
.OrderByDescending(p => p.IsWinner)
.ThenBy(p => p.Points)
.ToList();
}
private string GetPlayerName(Guid playerId)
{
var person = DayState.Value.AvailablePersons.FirstOrDefault(p => p.Id == playerId);
return person?.Name ?? "Unbekannt";
}
private Severity GetLastThrowSeverity()
{
if (_model?.LastThrowWasShitNumber == true || _model?.LastThrowWasGutter == true)
{
return Severity.Error;
}
return Severity.Info;
}
private string GetPointsStyle(PlayerStatsRow row)
{
if (row.IsWinner)
{
return "color: var(--mud-palette-success); font-weight: bold;";
}
if (_model?.IsGameOver == true)
{
return "color: var(--mud-palette-error);";
}
if (row.Points <= 10)
{
return "color: var(--mud-palette-warning);";
}
return "";
}
public void Dispose()
{
GameState.StateChanged -= OnGameStateChanged;
}
private record PlayerStatsRow
{
public Guid PlayerId { get; init; }
public string PlayerName { get; init; } = "";
public int Points { get; init; }
public bool IsWinner { get; init; }
public bool IsCurrentPlayer { get; init; }
}
}