using Shogi.Contracts.Types; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace Shogi.Contracts.Api; public class MovePieceCommand : IValidatableObject { /// /// For serialization. /// public MovePieceCommand() { To = string.Empty; } /// /// Move a piece on the board. /// public MovePieceCommand(string from, string to, bool isPromotion) { From = from; To = to; IsPromotion = isPromotion; } /// /// Add a piece to the board from the hand. /// public MovePieceCommand(WhichPiece pieceFromHand, string to) { PieceFromHand = pieceFromHand; To = to; } /// /// Mutually exclusive with . /// Set this property to indicate moving a piece from the hand onto the board. /// public WhichPiece? PieceFromHand { get; set; } /// /// Board position notation, like A3 or G1 /// Mutually exclusive with . /// Set this property to indicate moving a piece from the board to another position on the board. /// public string? From { get; set; } /// /// Board position notation, like A3 or G1 /// [Required] public string To { get; set; } public bool? IsPromotion { get; set; } public IEnumerable Validate(ValidationContext validationContext) { if (PieceFromHand.HasValue && !string.IsNullOrWhiteSpace(From)) { yield return new ValidationResult($"{nameof(PieceFromHand)} and {nameof(From)} are mutually exclusive properties."); } if (PieceFromHand.HasValue && IsPromotion.HasValue) { yield return new ValidationResult($"{nameof(PieceFromHand)} and {nameof(IsPromotion)} are mutually exclusive properties."); } if (!Regex.IsMatch(To, "[A-I][1-9]")) { yield return new ValidationResult($"{nameof(To)} must be a valid board position, between A1 and I9"); } if (!string.IsNullOrEmpty(From) && !Regex.IsMatch(From, "[A-I][1-9]")) { yield return new ValidationResult($"{nameof(From)} must be a valid board position, between A1 and I9"); } } }