Add submission CRUD with pagination and role scoping, challenge/location binding, automatic keyword extraction, a validated status workflow, and domain events for matchmaking and notifications. Create a problem record together with each submission.
71 lines
1.8 KiB
C#
71 lines
1.8 KiB
C#
using System.Text;
|
|
|
|
namespace TarninaHub.Application.Text;
|
|
|
|
public static class KeywordExtractor
|
|
{
|
|
private static readonly HashSet<string> StopWords = new(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
"i", "w", "we", "na", "z", "do", "nie", "że", "się", "jest", "to", "dla", "od", "po",
|
|
"o", "a", "ale", "jak", "co", "oraz", "przez", "przy", "tak", "już", "czy", "ich",
|
|
"the", "and", "for", "with", "this", "that", "are", "was",
|
|
};
|
|
|
|
public static IReadOnlyList<string> Extract(string text, int max = 8)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text) || max <= 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
|
var order = new List<string>();
|
|
|
|
foreach (var rawToken in Tokenize(text))
|
|
{
|
|
var token = rawToken.ToLowerInvariant();
|
|
|
|
if (token.Length < 3 || StopWords.Contains(token))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!counts.TryGetValue(token, out var count))
|
|
{
|
|
order.Add(token);
|
|
}
|
|
|
|
counts[token] = count + 1;
|
|
}
|
|
|
|
return order
|
|
.OrderByDescending(token => counts[token])
|
|
.ThenBy(token => order.IndexOf(token))
|
|
.Take(max)
|
|
.ToList();
|
|
}
|
|
|
|
private static IEnumerable<string> Tokenize(string text)
|
|
{
|
|
var buffer = new StringBuilder();
|
|
|
|
foreach (var character in text)
|
|
{
|
|
if (char.IsLetter(character))
|
|
{
|
|
buffer.Append(character);
|
|
}
|
|
else if (buffer.Length > 0)
|
|
{
|
|
yield return buffer.ToString();
|
|
buffer.Clear();
|
|
}
|
|
}
|
|
|
|
if (buffer.Length > 0)
|
|
{
|
|
yield return buffer.ToString();
|
|
}
|
|
}
|
|
}
|