using System.Text.Json.Serialization; using ChessCubing.App.Services; namespace ChessCubing.App.Models; public sealed class MatchConfig { [JsonPropertyName("matchLabel")] public string MatchLabel { get; set; } = "Rencontre ChessCubing"; [JsonPropertyName("competitionMode")] public bool CompetitionMode { get; set; } [JsonPropertyName("mode")] public string Mode { get; set; } = MatchEngine.ModeTwice; [JsonPropertyName("preset")] public string Preset { get; set; } = MatchEngine.PresetFast; [JsonPropertyName("blockDurationMs")] public long BlockDurationMs { get; set; } = MatchEngine.DefaultBlockDurationMs; [JsonPropertyName("moveLimitMs")] public long MoveLimitMs { get; set; } = MatchEngine.DefaultMoveLimitMs; [JsonPropertyName("timeInitialMs")] public long TimeInitialMs { get; set; } = MatchEngine.TimeModeInitialClockMs; [JsonPropertyName("whiteName")] public string WhiteName { get; set; } = "Blanc"; [JsonPropertyName("blackName")] public string BlackName { get; set; } = "Noir"; [JsonPropertyName("arbiterName")] public string ArbiterName { get; set; } = string.Empty; [JsonPropertyName("eventName")] public string EventName { get; set; } = string.Empty; [JsonPropertyName("notes")] public string Notes { get; set; } = string.Empty; } public sealed class MatchState { [JsonPropertyName("schemaVersion")] public int SchemaVersion { get; set; } = 3; [JsonPropertyName("config")] public MatchConfig Config { get; set; } = new(); [JsonPropertyName("phase")] public string Phase { get; set; } = MatchEngine.PhaseBlock; [JsonPropertyName("running")] public bool Running { get; set; } [JsonPropertyName("lastTickAt")] public long? LastTickAt { get; set; } [JsonPropertyName("blockNumber")] public int BlockNumber { get; set; } = 1; [JsonPropertyName("currentTurn")] public string CurrentTurn { get; set; } = MatchEngine.ColorWhite; [JsonPropertyName("blockRemainingMs")] public long BlockRemainingMs { get; set; } = MatchEngine.DefaultBlockDurationMs; [JsonPropertyName("moveRemainingMs")] public long MoveRemainingMs { get; set; } = MatchEngine.DefaultMoveLimitMs; [JsonPropertyName("quota")] public int Quota { get; set; } = 6; [JsonPropertyName("moves")] public PlayerIntPair Moves { get; set; } = new(); [JsonPropertyName("clocks")] public PlayerLongPair? Clocks { get; set; } [JsonPropertyName("lastMover")] public string? LastMover { get; set; } [JsonPropertyName("awaitingBlockClosure")] public bool AwaitingBlockClosure { get; set; } [JsonPropertyName("closureReason")] public string ClosureReason { get; set; } = string.Empty; [JsonPropertyName("result")] public string? Result { get; set; } [JsonPropertyName("cube")] public CubeState Cube { get; set; } = new(); [JsonPropertyName("doubleCoup")] public DoubleCoupState DoubleCoup { get; set; } = new(); [JsonPropertyName("history")] public List History { get; set; } = []; } public sealed class PlayerIntPair { [JsonPropertyName("white")] public int White { get; set; } [JsonPropertyName("black")] public int Black { get; set; } } public sealed class PlayerLongPair { [JsonPropertyName("white")] public long White { get; set; } [JsonPropertyName("black")] public long Black { get; set; } } public sealed class PlayerNullableLongPair { [JsonPropertyName("white")] public long? White { get; set; } [JsonPropertyName("black")] public long? Black { get; set; } } public sealed class CubeState { [JsonPropertyName("number")] public int? Number { get; set; } [JsonPropertyName("running")] public bool Running { get; set; } [JsonPropertyName("startedAt")] public long? StartedAt { get; set; } [JsonPropertyName("elapsedMs")] public long ElapsedMs { get; set; } [JsonPropertyName("phaseAlertPending")] public bool PhaseAlertPending { get; set; } [JsonPropertyName("times")] public PlayerNullableLongPair Times { get; set; } = new(); [JsonPropertyName("playerState")] public CubePlayerStates PlayerState { get; set; } = new(); [JsonPropertyName("round")] public int Round { get; set; } = 1; [JsonPropertyName("history")] public List History { get; set; } = []; } public sealed class CubePlayerStates { [JsonPropertyName("white")] public CubePlayerState White { get; set; } = new(); [JsonPropertyName("black")] public CubePlayerState Black { get; set; } = new(); } public sealed class CubePlayerState { [JsonPropertyName("running")] public bool Running { get; set; } [JsonPropertyName("startedAt")] public long? StartedAt { get; set; } [JsonPropertyName("elapsedMs")] public long ElapsedMs { get; set; } } public sealed class DoubleCoupState { [JsonPropertyName("eligible")] public bool Eligible { get; set; } [JsonPropertyName("step")] public int Step { get; set; } [JsonPropertyName("starter")] public string Starter { get; set; } = MatchEngine.ColorWhite; } public sealed class MatchHistoryEntry { [JsonPropertyName("message")] public string Message { get; set; } = string.Empty; [JsonPropertyName("time")] public string Time { get; set; } = string.Empty; } public sealed class CubeHistoryEntry { [JsonPropertyName("blockNumber")] public int BlockNumber { get; set; } [JsonPropertyName("number")] public int? Number { get; set; } [JsonPropertyName("white")] public long? White { get; set; } [JsonPropertyName("black")] public long? Black { get; set; } } public sealed class SetupFormModel { public bool CompetitionMode { get; set; } public string MatchLabel { get; set; } = string.Empty; public string Mode { get; set; } = MatchEngine.ModeTwice; public string Preset { get; set; } = MatchEngine.PresetFast; public int BlockMinutes { get; set; } = 3; public int MoveSeconds { get; set; } = 20; public int TimeInitialMinutes { get; set; } = 10; public string WhiteName { get; set; } = "Blanc"; public string BlackName { get; set; } = "Noir"; public string ArbiterName { get; set; } = string.Empty; public string EventName { get; set; } = string.Empty; public string Notes { get; set; } = string.Empty; public MatchConfig ToMatchConfig() { return new MatchConfig { MatchLabel = MatchEngine.SanitizeText(MatchLabel) is { Length: > 0 } label ? label : "Rencontre ChessCubing", CompetitionMode = CompetitionMode, Mode = Mode, Preset = Preset, BlockDurationMs = MatchEngine.NormalizeDurationMs(BlockMinutes * 60_000L, MatchEngine.DefaultBlockDurationMs), MoveLimitMs = MatchEngine.NormalizeDurationMs(MoveSeconds * 1_000L, MatchEngine.DefaultMoveLimitMs), TimeInitialMs = MatchEngine.NormalizeDurationMs(TimeInitialMinutes * 60_000L, MatchEngine.TimeModeInitialClockMs), WhiteName = MatchEngine.SanitizeText(WhiteName) is { Length: > 0 } white ? white : "Blanc", BlackName = MatchEngine.SanitizeText(BlackName) is { Length: > 0 } black ? black : "Noir", ArbiterName = MatchEngine.SanitizeText(ArbiterName), EventName = MatchEngine.SanitizeText(EventName), Notes = MatchEngine.SanitizeText(Notes), }; } public static SetupFormModel CreateDemo() { return new SetupFormModel { CompetitionMode = true, MatchLabel = "Demo officielle ChessCubing", Mode = MatchEngine.ModeTwice, Preset = MatchEngine.PresetFreeze, BlockMinutes = 3, MoveSeconds = 20, TimeInitialMinutes = 10, WhiteName = "Nora", BlackName = "Leo", ArbiterName = "Arbitre demo", EventName = "Session telephone", Notes = "8 cubes verifies, variante prete, tirage au sort effectue.", }; } } public sealed record MatchPresetInfo(string Label, int Quota, string Description); public sealed record MatchModeInfo(string Label, string Subtitle); public sealed record TimeAdjustmentPreview( string BlockType, string? Winner, long CappedWhite, long CappedBlack, long WhiteDelta, long BlackDelta, long WhiteAfter, long BlackAfter);