144 lines
6.0 KiB
C#
144 lines
6.0 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
using PARR.Core.Repositories.Interfaces.Unit;
|
|
using PARR.Core.Services.UnitFilterService.Models;
|
|
using PARR.Domain.Entities.Job;
|
|
using PARR.TemplateMatcher.Services.Interfaces;
|
|
|
|
internal class UnitInTemplateConflictMapper : IUnitInTemplateConflictMapper
|
|
{
|
|
private readonly ILogger<UnitInTemplateConflictMapper> logger;
|
|
private readonly IUnitRepository unitRepository;
|
|
private readonly IUnitKiiUnitRepository unitKiiUnitRepository;
|
|
|
|
public UnitInTemplateConflictMapper(
|
|
ILogger<UnitInTemplateConflictMapper> logger,
|
|
IUnitRepository unitRepository,
|
|
IUnitKiiUnitRepository unitKiiUnitRepository)
|
|
{
|
|
this.logger = logger;
|
|
this.unitRepository = unitRepository;
|
|
this.unitKiiUnitRepository = unitKiiUnitRepository;
|
|
}
|
|
|
|
public async Task<Dictionary<Guid, List<Guid>>> BuildMappingAsync(
|
|
IEnumerable<UnitFilterResultDto> unitFilterResults,
|
|
Job maxJob,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
logger.LogDebug("Начало разрешения конфликтов и построения маппинга для юнитов в шаблонах.");
|
|
|
|
var unitFilterResultsList = unitFilterResults.ToList();
|
|
if (!unitFilterResultsList.Any())
|
|
return new Dictionary<Guid, List<Guid>>();
|
|
|
|
var potentialAssignments = new Dictionary<Guid, List<Guid>>();
|
|
var allPotentialRelatedUnitIds = new HashSet<Guid>();
|
|
var allUnitInTemplateIds = new HashSet<Guid>();
|
|
|
|
foreach (var dto in unitFilterResultsList)
|
|
{
|
|
var relatedUnitIds = maxJob.IsParentRelationships == true
|
|
? dto.Children.Select(c => c.UnitId).ToList()
|
|
: dto.Parents.Select(p => p.UnitId).ToList();
|
|
|
|
var unitInTemplateId = dto.Id;
|
|
|
|
allUnitInTemplateIds.Add(unitInTemplateId);
|
|
allPotentialRelatedUnitIds.UnionWith(relatedUnitIds);
|
|
|
|
foreach (var relatedId in relatedUnitIds)
|
|
{
|
|
if (!potentialAssignments.TryGetValue(relatedId, out var list))
|
|
{
|
|
list = new List<Guid>();
|
|
potentialAssignments[relatedId] = list;
|
|
}
|
|
list.Add(unitInTemplateId);
|
|
}
|
|
}
|
|
|
|
if (!allPotentialRelatedUnitIds.Any())
|
|
return new Dictionary<Guid, List<Guid>>();
|
|
|
|
var relatedUnitNames = await unitRepository.Get()
|
|
.AsNoTracking()
|
|
.Where(u => allPotentialRelatedUnitIds.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id, u => u.Name ?? u.Id.ToString(), cancellationToken);
|
|
|
|
// Загружаем идентификаторы КИИ через ваш реальный репозиторий
|
|
var kiiUnitIds = new HashSet<Guid>(await unitKiiUnitRepository.Get()
|
|
.Select(k => k.UnitId)
|
|
.ToListAsync(cancellationToken));
|
|
|
|
logger.LogDebug("Загружено {KiiCount} идентификаторов КИИ юнитов для приоритезации.", kiiUnitIds.Count);
|
|
|
|
var unitInTemplateToBestRelatedUnit = new Dictionary<Guid, Guid>();
|
|
|
|
foreach (var unitInTemplateId in allUnitInTemplateIds)
|
|
{
|
|
var candidates = potentialAssignments
|
|
.Where(kvp => kvp.Value.Contains(unitInTemplateId))
|
|
.Select(kvp => kvp.Key)
|
|
.ToList();
|
|
|
|
if (candidates.Count == 0) continue;
|
|
if (candidates.Count == 1)
|
|
{
|
|
unitInTemplateToBestRelatedUnit[unitInTemplateId] = candidates[0];
|
|
continue;
|
|
}
|
|
|
|
var kiiCandidates = candidates.Where(id => kiiUnitIds.Contains(id)).ToList();
|
|
var candidatesToConsider = kiiCandidates.Any() ? kiiCandidates : candidates;
|
|
|
|
var relationshipCounts = new Dictionary<Guid, int>();
|
|
foreach (var candidateId in candidatesToConsider)
|
|
{
|
|
int totalRelationships = 0;
|
|
foreach (var dto in unitFilterResultsList)
|
|
{
|
|
if (maxJob.IsParentRelationships == true && dto.Children.Any(c => c.UnitId == candidateId))
|
|
totalRelationships += dto.Children.Count;
|
|
else if (maxJob.IsParentRelationships == false && dto.Parents.Any(p => p.UnitId == candidateId))
|
|
totalRelationships += dto.Parents.Count;
|
|
}
|
|
relationshipCounts[candidateId] = totalRelationships;
|
|
}
|
|
|
|
var bestCandidate = candidatesToConsider[0];
|
|
int bestCount = relationshipCounts[bestCandidate];
|
|
|
|
foreach (var candidateId in candidatesToConsider.Skip(1))
|
|
{
|
|
int currentCount = relationshipCounts[candidateId];
|
|
if (currentCount > bestCount ||
|
|
(currentCount == bestCount && string.Compare(
|
|
relatedUnitNames.GetValueOrDefault(candidateId, candidateId.ToString()),
|
|
relatedUnitNames.GetValueOrDefault(bestCandidate, bestCandidate.ToString()),
|
|
StringComparison.OrdinalIgnoreCase) < 0))
|
|
{
|
|
bestCandidate = candidateId;
|
|
bestCount = currentCount;
|
|
}
|
|
}
|
|
|
|
unitInTemplateToBestRelatedUnit[unitInTemplateId] = bestCandidate;
|
|
}
|
|
|
|
logger.LogDebug("Разрешение конфликтов завершено. Найдено {Count} однозначных назначений.", unitInTemplateToBestRelatedUnit.Count);
|
|
|
|
var reverseMapping = new Dictionary<Guid, List<Guid>>();
|
|
foreach (var kvp in unitInTemplateToBestRelatedUnit)
|
|
{
|
|
if (!reverseMapping.TryGetValue(kvp.Value, out var list))
|
|
{
|
|
list = new List<Guid>();
|
|
reverseMapping[kvp.Value] = list;
|
|
}
|
|
list.Add(kvp.Key);
|
|
}
|
|
|
|
return reverseMapping;
|
|
}
|
|
} |