feat(templateMatcher): refactoring

This commit is contained in:
Mikhail Kuznetsov
2025-12-26 21:47:53 +10:00
parent e04d2b628c
commit e8db55400c
11 changed files with 679 additions and 554 deletions

View File

@@ -12,6 +12,10 @@ namespace PARR.DAL.DomainServices.Implementations
{
internal class UnitFilterService : IUnitFilterService
{
#if DEBUG
private readonly Guid targetUnitId = Guid.Parse("d4322a08-246b-4380-8953-8ce4a8446235");
#endif
private readonly ILogger<UnitFilterService> logger;
private readonly IJobService jobService;
private readonly IUnitService unitService;
@@ -118,6 +122,19 @@ namespace PARR.DAL.DomainServices.Implementations
logger.LogDebug("Базовый фильтр по Name '{NameFilter}' дал {Count} юнитов", filter.UnitFilter, initialUnitIds.Count);
#if DEBUG
// ✅ Отладка: проверить, есть ли юнит в initialUnitIds
if (initialUnitIds.Contains(targetUnitId))
{
logger.LogDebug("Юнит {TargetUnitId} найден в initialUnitIds.", targetUnitId);
}
else
{
logger.LogDebug("Юнит {TargetUnitId} НЕ найден в initialUnitIds.", targetUnitId);
//continue; // ❌ юнит отсеялся на этом этапе
}
#endif
if (!initialUnitIds.Any())
{
logger.LogDebug("Фильтр #{Index}: 0 юнитов после UnitFilter. Пропускаем.", filterNumber);
@@ -249,14 +266,42 @@ namespace PARR.DAL.DomainServices.Implementations
candidateUnits = ApplyFieldFilter(candidateUnits, fieldFilter);
}
logger.LogDebug("После FieldFilter осталось {Count} юнитов", candidateUnits.Count());
#if DEBUG
// ✅ Отладка: проверить, есть ли юнит в candidateUnits после FieldFilter
var candidateListAfterFieldFilter = candidateUnits.ToList();
if (candidateListAfterFieldFilter.Any(u => u.Id == targetUnitId))
{
logger.LogDebug("Юнит {TargetUnitId} найден в candidateUnits после FieldFilter.", targetUnitId);
}
else
{
logger.LogDebug("Юнит {TargetUnitId} НЕ найден в candidateUnits после FieldFilter.", targetUnitId);
//continue; // ❌ юнит отсеялся на этом этапе
}
logger.LogDebug("После FieldFilter осталось {Count} юнитов", candidateListAfterFieldFilter.Count);
#endif
foreach (var relFilter in filter.RelationshipFilters)
{
candidateUnits = ApplyRelationshipFilterToQuery(candidateUnits, relFilter);
}
logger.LogDebug("После RelationshipFilter осталось {Count} юнитов", candidateUnits.Count());
#if DEBUG
// ✅ Отладка: проверить, есть ли юнит в candidateUnits после RelationshipFilter
var candidateListAfterRelFilter = candidateUnits.ToList();
if (candidateListAfterRelFilter.Any(u => u.Id == targetUnitId))
{
logger.LogDebug("Юнит {TargetUnitId} найден в candidateUnits после RelationshipFilter.", targetUnitId);
}
else
{
logger.LogDebug("Юнит {TargetUnitId} НЕ найден в candidateUnits после RelationshipFilter.", targetUnitId);
//continue; // ❌ юнит отсеялся на этом этапе
}
logger.LogDebug("После RelationshipFilter осталось {Count} юнитов", candidateListAfterRelFilter.Count);
#endif
// 9 Umbrella-фильтр
var finalUnits = candidateUnits.AsEnumerable();
@@ -264,6 +309,19 @@ namespace PARR.DAL.DomainServices.Implementations
{
finalUnits = ApplyRelationshipCountFilter(finalUnits, job, filter.RelationshipFilters);
logger.LogDebug("После Umbrella-фильтра осталось {Count} юнитов", finalUnits.Count());
#if DEBUG
// ✅ Отладка: проверить, есть ли юнит в finalUnits после Umbrella
if (finalUnits.Any(u => u.Id == targetUnitId))
{
logger.LogDebug("Юнит {TargetUnitId} найден в finalUnits после Umbrella-фильтра.", targetUnitId);
}
else
{
logger.LogDebug("Юнит {TargetUnitId} НЕ найден в finalUnits после Umbrella-фильтра.", targetUnitId);
//continue; // ❌ юнит отсеялся на этом этапе
}
#endif
}
// 10 Взять ID
@@ -272,6 +330,19 @@ namespace PARR.DAL.DomainServices.Implementations
.Take(remaining)
.ToList();
#if DEBUG
// ✅ Отладка: проверить, есть ли юнит в newIds
if (newIds.Contains(targetUnitId))
{
logger.LogDebug("Юнит {TargetUnitId} найден в newIds.", targetUnitId);
}
else
{
logger.LogDebug("Юнит {TargetUnitId} НЕ найден в newIds.", targetUnitId);
// ❌ юнит отсеялся на этапе Take(remaining), если его не было в finalUnits
}
#endif
collectedIds.UnionWith(newIds);
logger.LogDebug("Фильтр #{Index}: найдено {Count} Unit'ов. Всего: {Total}",
filterNumber, newIds.Count, collectedIds.Count);
@@ -287,6 +358,18 @@ namespace PARR.DAL.DomainServices.Implementations
logger.LogInformation("Job {JobId}: из {FilterCount} фильтров получено {UnitCount} уникальных Unit'ов",
job.Id, job.UnitFilters.Count, result.Count);
#if DEBUG
// ✅ Отладка: проверить, есть ли юнит в result
if (result.Contains(targetUnitId))
{
logger.LogDebug("Юнит {TargetUnitId} найден в финальном результате.", targetUnitId);
}
else
{
logger.LogDebug("Юнит {TargetUnitId} НЕ найден в финальном результате.", targetUnitId);
}
#endif
return result;
}
@@ -403,15 +486,45 @@ namespace PARR.DAL.DomainServices.Implementations
return query.AsEnumerable().Where(dto =>
{
#if DEBUG
// ✅ Отладка: проверить, это нужный юнит
if (dto.Id == targetUnitId)
{
logger.LogDebug("Проверяем юнит {TargetUnitId} с {ParentCount} родителями и {ChildCount} детьми.",
targetUnitId, dto.Parents.Count, dto.Children.Count);
}
#endif
var links = isParent ? dto.Parents : dto.Children;
if (links == null || !links.Any())
{
#if DEBUG
// ✅ Отладка: юнит не имеет связей
if (dto.Id == targetUnitId)
{
logger.LogDebug("Юнит {TargetUnitId}: нет связей ({Direction}), результат фильтра: {Result}",
targetUnitId, isParent ? "Parent" : "Child", isFullMatch && isInverse);
}
#endif
// Для IsFullMatch/IsInverse — "все подходят", т.е. true
// Для остальных — false
return isFullMatch && isInverse;
}
#if DEBUG
// ✅ Отладка: проверить, какие связи у юнита
if (dto.Id == targetUnitId)
{
logger.LogDebug("Юнит {TargetUnitId}: {Count} связей ({Direction}).", targetUnitId, links.Count, isParent ? "Parent" : "Child");
foreach (var link in links)
{
logger.LogDebug(" Связь: UnitId={LinkUnitId}, Name={LinkName}, Values=[{Values}]", link.UnitId, link.Name, string.Join(", ", link.Values.Select(v => $"{v.FieldId}={v.Value}")));
}
}
#endif
var hasMatchingLinks = links.Any(link =>
{
var hasMatch = link.Values.Any(v =>
@@ -423,9 +536,25 @@ namespace PARR.DAL.DomainServices.Implementations
v.Value.Contains(valueMask, StringComparison.OrdinalIgnoreCase))
);
#if DEBUG
// ✅ Отладка: проверить, какая связь подходит
if (dto.Id == targetUnitId)
{
logger.LogDebug(" Проверка связи {LinkUnitId}: hasMatch={HasMatch} (ValueMask={ValueMask}, FieldId={FieldId})", link.UnitId, hasMatch, valueMask, fieldId);
}
#endif
return isInverse ? !hasMatch : hasMatch;
});
#if DEBUG
// ✅ Отладка: результат hasMatchingLinks
if (dto.Id == targetUnitId)
{
logger.LogDebug(" hasMatchingLinks = {HasMatchingLinks}, isInverse = {IsInverse}", hasMatchingLinks, isInverse);
}
#endif
if (isFullMatch)
{
var allMatch = links.All(link =>
@@ -439,9 +568,25 @@ namespace PARR.DAL.DomainServices.Implementations
v.Value.Contains(valueMask, StringComparison.OrdinalIgnoreCase))
);
#if DEBUG
// ✅ Отладка: проверить, все ли связи подходят
if (dto.Id == targetUnitId)
{
logger.LogDebug(" Проверка связи {LinkUnitId} для FullMatch: hasMatch={HasMatch}", link.UnitId, hasMatch);
}
#endif
return isInverse ? !hasMatch : hasMatch;
});
#if DEBUG
// ✅ Отладка: результат allMatch
if (dto.Id == targetUnitId)
{
logger.LogDebug(" allMatch = {AllMatch}, isFullMatch = {IsFullMatch}", allMatch, isFullMatch);
}
#endif
return allMatch;
}