using System.Text.Json.Serialization; namespace GoodWood.Application.Games; /// /// Base class for game events that require UI notification (dialogs, toasts, etc.). /// Events have a unique ID to prevent duplicate display. /// [JsonPolymorphic(TypeDiscriminatorPropertyName = "$type")] [JsonDerivedType(typeof(PlayerEliminatedEvent), "PlayerEliminated")] [JsonDerivedType(typeof(PlayerWonEvent), "PlayerWon")] [JsonDerivedType(typeof(TeamWonEvent), "TeamWon")] [JsonDerivedType(typeof(GameEndedEvent), "GameEnded")] [JsonDerivedType(typeof(FoxChangedEvent), "FoxChanged")] public abstract record GameEvent { /// /// Unique identifier for this event instance. /// public Guid EventId { get; init; } = Guid.NewGuid(); /// /// Timestamp when the event was created. /// public DateTime CreatedAt { get; init; } = DateTime.UtcNow; /// /// Game-specific message to display in the UI. /// public string? Message { get; init; } } /// /// Event when a player is eliminated from the game. /// public record PlayerEliminatedEvent : GameEvent { /// /// ID of the eliminated player. /// public required Guid PlayerId { get; init; } /// /// Elimination rank (1 = first eliminated, 2 = second, etc.). /// public int EliminationRank { get; init; } /// /// Number of players still active after this elimination. /// public int RemainingPlayerCount { get; init; } } /// /// Event when a single player wins the game. /// public record PlayerWonEvent : GameEvent { /// /// ID of the winning player. /// public required Guid PlayerId { get; init; } } /// /// Event when a team wins the game. /// public record TeamWonEvent : GameEvent { /// /// Name or identifier of the winning team. /// public required string TeamName { get; init; } /// /// IDs of players in the winning team. /// public required IReadOnlyList PlayerIds { get; init; } } /// /// Event when the fox role changes (fox escaped or was caught). /// public record FoxChangedEvent : GameEvent { /// /// ID of the player who was fox. /// public required Guid FoxPlayerId { get; init; } /// /// True if the fox escaped, false if caught by hunters. /// public bool FoxEscaped { get; init; } /// /// ID of the next fox (null if game is over). /// public Guid? NextFoxPlayerId { get; init; } } /// /// Event when the game ends (covers any end scenario). /// public record GameEndedEvent : GameEvent { /// /// Optional winner ID (null for draws or no-winner scenarios). /// public Guid? WinnerId { get; init; } /// /// Optional winning team name. /// public string? WinningTeamName { get; init; } /// /// Whether the game ended in a draw. /// public bool IsDraw { get; init; } }