using System.Text.RegularExpressions; using GeradoresService.Core; namespace GeradoresService.Generators.Outros; /// Matrículas portuguesas em todos os formatos desde 1937. Apenas formato. public sealed partial class MatriculaGenerator : GeneratorBase { // K, W e Y não eram usadas nas matrículas portuguesas. private const string Letters = "ABCDEFGHIJLMNOPQRSTUVXZ"; private sealed record Format(string Key, string Label, string Mask, string Period); private static readonly Format[] Formats = [ new("2020", "AA-00-AA (desde 2020)", "LL-DD-LL", "2020 – actualidade"), new("2005", "00-AA-00 (2005–2020)", "DD-LL-DD", "2005 – 2020"), new("1992", "00-00-AA (1992–2005)", "DD-DD-LL", "1992 – 2005"), new("1937", "AA-00-00 (1937–1992)", "LL-DD-DD", "1937 – 1992"), ]; public override string Id => "matricula"; public override string Name => "Matrícula"; public override string Category => Categories.Outros; public override string Description => "Matrícula automóvel portuguesa em qualquer um dos formatos."; public override bool HasChecksum => false; public override IReadOnlyList Options => [ Option("formato", "Formato", "2020", [.. Formats.Select(f => (f.Key, f.Label)), ("qualquer", "Qualquer")]), ]; public override GeneratedItem Generate(GeneratorContext context) { var key = context.Option(Options[0]); var format = key == "qualquer" ? context.Pick(Formats) : Formats.Single(f => f.Key == key); var plate = string.Concat(format.Mask.Select(c => c switch { 'L' => Letters[context.Random.Next(Letters.Length)], 'D' => (char)('0' + context.Random.Next(10)), _ => c, })); return new GeneratedItem(plate); } public override ValidationResult Validate(string value) { var plate = Checksums.Clean(value).ToUpperInvariant(); if (plate.Length != 6 || !plate.All(char.IsAsciiLetterOrDigit)) return ValidationResult.WrongFormat("Uma matrícula tem 6 caracteres em 3 pares (ex.: AA-00-AA)."); var mask = string.Concat(plate.Chunk(2).Select(p => p.All(char.IsAsciiDigit) ? "DD" : p.All(char.IsAsciiLetter) ? "LL" : "??")); var masked = $"{mask[..2]}-{mask[2..4]}-{mask[4..]}"; var format = Formats.FirstOrDefault(f => f.Mask == masked); if (format is null) return ValidationResult.WrongFormat("Não corresponde a nenhum formato de matrícula portuguesa."); var formatted = $"{plate[..2]}-{plate[2..4]}-{plate[4..]}"; if (plate.Any(c => c is 'K' or 'W' or 'Y')) return ValidationResult.BadChecksum("As letras K, W e Y não são usadas em matrículas portuguesas."); return ValidationResult.Valid(formatted, $"Matrícula válida (formato {format.Period}).", [$"Formato: {format.Label}"]); } }