SaaS-мониторинг Telegram: ядро (модули Cards/Kanban/Pipeline/Tenants/Settings/ Discovery, Api, Infrastructure), сервисы telegram/ai/ml/storage, фронт Vue, контракты и grpc-hosting, деплой-конфиги (dev/prod/observability/CI-раннер), Gitea Actions CI, документация (ТЗ, техдок, api-map, код-стайл, планы, бэклог). Текущее состояние: все этапы роадмапа 0–12 закрыты, сборка 5 sln 0/0, тесты 1340/130/52/38/9 зелёные.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
using System.Globalization;
|
||||
using Deal.Modules.Kanban.Application.Models;
|
||||
|
||||
namespace Deal.Modules.Kanban.Application.ColumnRules;
|
||||
|
||||
/// <summary>
|
||||
/// Человекочитаемое описание правил колонки для note/подсказки.
|
||||
/// </summary>
|
||||
public static class RulesDescriber
|
||||
{
|
||||
/// <summary>
|
||||
/// Описывает правила колонки.
|
||||
/// </summary>
|
||||
/// <param name="rules">Правила колонки (null/пустые → «без правил (решает ИИ/ML)»).</param>
|
||||
/// <returns>Строка-расшифровка для UI/промпта.</returns>
|
||||
public static string Describe(ContainerRulesDto? rules)
|
||||
{
|
||||
if (rules is null)
|
||||
{
|
||||
return NoRulesText;
|
||||
}
|
||||
|
||||
var parts = new List<string>();
|
||||
if (rules.Direction.Count > 0)
|
||||
{
|
||||
parts.Add($"направление: {JoinLimited(rules.Direction, DirectionLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Stack.Count > 0)
|
||||
{
|
||||
parts.Add($"стек: {JoinLimited(rules.Stack, TermsLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Keywords.Count > 0)
|
||||
{
|
||||
parts.Add($"слова: {JoinLimited(rules.Keywords, TermsLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Grade.Count > 0)
|
||||
{
|
||||
parts.Add($"грейд: {JoinLimited(rules.Grade, TermsLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Levels is { Count: > 0 })
|
||||
{
|
||||
parts.Add($"уровень: {JoinLimited(rules.Levels, TermsLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Locations is { Count: > 0 })
|
||||
{
|
||||
parts.Add($"локация: {JoinLimited(rules.Locations, TermsLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Types is { Count: > 0 })
|
||||
{
|
||||
parts.Add($"тип: {JoinLimited(rules.Types, TermsLimit)}");
|
||||
}
|
||||
|
||||
if (rules.Exclude.Count > 0)
|
||||
{
|
||||
parts.Add($"исключено: {JoinLimited(rules.Exclude, TermsLimit)}");
|
||||
}
|
||||
|
||||
AddRangePart(parts, rules.Budget, "бюджет");
|
||||
AddRangePart(parts, rules.Prices, "цена");
|
||||
|
||||
if (parts.Count == 0)
|
||||
{
|
||||
return NoRulesText;
|
||||
}
|
||||
|
||||
string mode = string.Equals(rules.Mode, "any", StringComparison.OrdinalIgnoreCase)
|
||||
? AnyModePrefix
|
||||
: AllModePrefix;
|
||||
return mode + " · " + string.Join("; ", parts);
|
||||
}
|
||||
|
||||
private const string NoRulesText = "без правил (решает ИИ/ML)";
|
||||
|
||||
private const string AllModePrefix = "все условия";
|
||||
|
||||
// Префикс режима «любое из условий».
|
||||
private const string AnyModePrefix = "любое из условий";
|
||||
|
||||
private const int DirectionLimit = 6;
|
||||
|
||||
private const int TermsLimit = 8;
|
||||
|
||||
// Добавляет в описание диапазон группы (бюджет/цена), если задана хотя бы одна граница.
|
||||
// parts: Накопитель частей описания.
|
||||
// range: Диапазон группы (null — группа выключена).
|
||||
// title: Подпись группы («бюджет»/«цена»).
|
||||
private static void AddRangePart(
|
||||
List<string> parts,
|
||||
BudgetRangeDto? range,
|
||||
string title)
|
||||
{
|
||||
if (range is null || (range.From is null && range.To is null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string lo = range.From is not null ? range.From.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
|
||||
string hi = range.To is not null ? range.To.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
|
||||
string cur = range.Cur ?? string.Empty;
|
||||
parts.Add($"{title}: {lo}–{hi} {cur}".Replace("– ", "–").Replace(" –", "–"));
|
||||
}
|
||||
|
||||
private static string JoinLimited(IReadOnlyList<string> terms, int limit)
|
||||
{
|
||||
int count = Math.Min(terms.Count, limit);
|
||||
return string.Join(", ", terms.Take(count));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user