Sube carpetas API, API.Tests, Application y Domain del Backend

This commit is contained in:
FrancoRu
2026-09-18 13:35:59 -03:00
parent bbb09554bb
commit 2eb4eeef03
572 changed files with 56405 additions and 0 deletions
@@ -0,0 +1,28 @@
using System;
namespace Application.Utils.Helper.Slug;
/// <summary>
/// Composes the display string a Match's slug is generated from, fed through SlugGenerator.GenerateUniqueSlugAsync.
/// </summary>
public static class MatchSlugSourceBuilder
{
/// <summary>
/// Placeholder team name used when a match's home or visitor team is not yet assigned.
/// </summary>
public const string UnassignedTeamPlaceholder = "TBD";
/// <summary>
/// Builds the slug source string for a match.
/// </summary>
/// <param name="homeTeamName">The home team's name, or null/empty when not yet assigned.</param>
/// <param name="visitorTeamName">The visitor team's name, or null/empty when not yet assigned.</param>
/// <param name="matchDate">The match's date.</param>
public static string Build(string? homeTeamName, string? visitorTeamName, DateTime matchDate)
{
string home = string.IsNullOrWhiteSpace(homeTeamName) ? UnassignedTeamPlaceholder : homeTeamName;
string visitor = string.IsNullOrWhiteSpace(visitorTeamName) ? UnassignedTeamPlaceholder : visitorTeamName;
return $"{home} vs {visitor} {matchDate:yyyy-MM-dd}";
}
}
@@ -0,0 +1,61 @@
using System;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Application.Utils.Helper.Slug;
/// <summary>
/// Generates lowercase, kebab-case, URL-friendly slugs from display names.
/// </summary>
public static partial class SlugGenerator
{
/// <summary>
/// Converts text into a lowercase, kebab-case slug.
/// </summary>
/// <param name="text">The display name to convert.</param>
/// <returns>The generated slug. Never null, may be empty for input with no alphanumeric characters.</returns>
public static string GenerateSlug(string text)
{
string normalized = text.Normalize(NormalizationForm.FormD);
StringBuilder withoutAccents = new(normalized.Length);
foreach (char character in normalized)
{
if (CharUnicodeInfo.GetUnicodeCategory(character) != UnicodeCategory.NonSpacingMark)
{
withoutAccents.Append(character);
}
}
string lowercase = withoutAccents.ToString().Normalize(NormalizationForm.FormC).ToLowerInvariant();
string hyphenated = NonAlphanumericRunRegex().Replace(lowercase, "-");
return hyphenated.Trim('-');
}
/// <summary>
/// Generates a slug from text and, when it collides with an existing slug, appends a numeric suffix until slugExists reports no collision.
/// </summary>
/// <param name="text">The display name to convert.</param>
/// <param name="slugExists">Predicate that checks whether a candidate slug is already taken.</param>
/// <returns>A unique slug derived from text.</returns>
public static async Task<string> GenerateUniqueSlugAsync(string text, Func<string, Task<bool>> slugExists)
{
string baseSlug = GenerateSlug(text);
string candidate = baseSlug;
int suffix = 1;
while (await slugExists(candidate))
{
suffix++;
candidate = $"{baseSlug}-{suffix}";
}
return candidate;
}
[GeneratedRegex("[^a-z0-9]+")]
private static partial Regex NonAlphanumericRunRegex();
}