From 62000e12917d3264e282c48d06944a389ab13b8d Mon Sep 17 00:00:00 2001 From: beo3000 Date: Sun, 28 Dec 2025 21:42:13 +0100 Subject: [PATCH] fix PlayerOrder DeathBox --- .../Game/DeathBox/DeathBoxBoard.razor | 16 +++--- src/Koogle.Web/Store/GameState/GameEffects.cs | 50 +++++++++++++++++-- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/Koogle.Web/Components/Game/DeathBox/DeathBoxBoard.razor b/src/Koogle.Web/Components/Game/DeathBox/DeathBoxBoard.razor index 0fd0081..31b72dc 100644 --- a/src/Koogle.Web/Components/Game/DeathBox/DeathBoxBoard.razor +++ b/src/Koogle.Web/Components/Game/DeathBox/DeathBoxBoard.razor @@ -208,7 +208,7 @@ } } - if (_model?.PlayerStates == null) + if (_model?.PlayerStates == null || _model.PlayerOrder == null) { return; } @@ -216,8 +216,12 @@ var currentPlayerId = gameState.Participants.CurrentPlayerId; var persons = DayState.Value.AvailablePersons; - foreach (var (playerId, state) in _model.PlayerStates) + // Iterate in PlayerOrder to maintain fixed display order + foreach (var playerId in _model.PlayerOrder) { + if (!_model.PlayerStates.TryGetValue(playerId, out var state)) + continue; + var person = persons.FirstOrDefault(p => p.Id == playerId); var playerName = person?.Name ?? "Unbekannt"; @@ -243,13 +247,7 @@ } } - // Sort: Winner first, then active players, then eliminated by order - _playerStats = _playerStats - .OrderByDescending(p => p.IsWinner) - .ThenBy(p => p.IsEliminated) - .ThenByDescending(p => p.IsCurrentPlayer) - .ThenBy(p => p.Marks) - .ToList(); + // No sorting - keep fixed PlayerOrder for display } private string GetPlayerName(Guid playerId) diff --git a/src/Koogle.Web/Store/GameState/GameEffects.cs b/src/Koogle.Web/Store/GameState/GameEffects.cs index 4890730..8c0b42b 100644 --- a/src/Koogle.Web/Store/GameState/GameEffects.cs +++ b/src/Koogle.Web/Store/GameState/GameEffects.cs @@ -62,6 +62,13 @@ public class GameEffects { try { + // Use PlayerOrder from GameModel if available (e.g., DeathBox randomizes order) + var playerIds = action.PlayerIds; + if (action.InitialGameModel != null) + { + playerIds = ExtractPlayerOrder(action.InitialGameModel) ?? playerIds; + } + var initialState = new GameStateSerializationDto { ThrowPanelAfter = MapThrowPanelToDto(ThrowPanelState.Initial with @@ -78,7 +85,7 @@ public class GameEffects }), Participants = new ParticipantsStateDto { - PlayerIds = action.PlayerIds, + PlayerIds = playerIds, // Use randomized order CurrentPlayerIndex = 0, Mode = (int)action.ParticipantsMode }, @@ -96,7 +103,7 @@ public class GameEffects DayId = action.DayId, ClubId = _clubContext.ClubId, GameType = action.GameTypeName, - PlayerIds = action.PlayerIds, + PlayerIds = playerIds, // Use randomized order InitialGameStateJson = JsonSerializer.Serialize(initialState, GameStateSerializationDto.JsonOptions) }; @@ -111,7 +118,7 @@ public class GameEffects var participants = new ParticipantsState { - PlayerIds = action.PlayerIds, + PlayerIds = playerIds, CurrentPlayerIndex = 0, Mode = action.ParticipantsMode }; @@ -1065,4 +1072,41 @@ public class GameEffects // Don't fail the throw recording if trigger fails } } + + /// + /// Extracts PlayerOrder from game model if available (e.g., DeathBox randomizes player order). + /// Returns null if the model doesn't have a PlayerOrder property. + /// + private static Guid[]? ExtractPlayerOrder(object? gameModel) + { + if (gameModel == null) return null; + + // Handle JsonElement (from deserialization) + if (gameModel is JsonElement jsonElement) + { + if (jsonElement.TryGetProperty("PlayerOrder", out var playerOrderProp) || + jsonElement.TryGetProperty("playerOrder", out playerOrderProp)) + { + try + { + return JsonSerializer.Deserialize(playerOrderProp.GetRawText()); + } + catch + { + return null; + } + } + return null; + } + + // Use reflection to check for PlayerOrder property + var type = gameModel.GetType(); + var property = type.GetProperty("PlayerOrder"); + if (property != null && property.PropertyType == typeof(Guid[])) + { + return property.GetValue(gameModel) as Guid[]; + } + + return null; + } }