PlotDirector/PlotLine/Services/CoreImportCharacterCandidateResolver.cs

63 lines
2.4 KiB
C#

using PlotLine.Models;
namespace PlotLine.Services;
public sealed record CoreImportExistingCharacterName(int CharacterID, string Name);
public sealed class CoreImportCharacterCandidateResolutionResult
{
public IReadOnlyList<ManuscriptScanCharacterCandidatePreview> Candidates { get; init; } = [];
public int AutoResolvedCount { get; init; }
}
public static class CoreImportCharacterCandidateResolver
{
public static CoreImportCharacterCandidateResolutionResult ResolveExactKnownMatches(
IReadOnlyList<ManuscriptScanCharacterCandidatePreview> candidates,
IReadOnlyList<CoreImportExistingCharacterName> existingNames)
{
var index = existingNames
.Select(item => new { Key = CoreImportBasicLocationDetector.StableKey(item.Name), item.CharacterID })
.Where(item => !string.IsNullOrWhiteSpace(item.Key))
.GroupBy(item => item.Key, StringComparer.Ordinal)
.ToDictionary(
group => group.Key,
group => group.Select(item => item.CharacterID).Distinct().ToList(),
StringComparer.Ordinal);
var resolved = 0;
var output = candidates.Select(candidate =>
{
var key = CoreImportBasicLocationDetector.StableKey(candidate.Name);
if (!string.IsNullOrWhiteSpace(key)
&& index.TryGetValue(key, out var matches)
&& matches.Count == 1)
{
resolved++;
return new ManuscriptScanCharacterCandidatePreview
{
TemporaryCharacterKey = candidate.TemporaryCharacterKey,
Name = candidate.Name,
MentionCount = candidate.MentionCount,
QualityScore = candidate.QualityScore,
Category = candidate.Category,
Reason = candidate.Reason,
ExistingCharacterID = matches[0],
IsExistingCharacterMatch = true,
IsAutoResolvedExistingCharacter = true,
SuggestedImportance = candidate.SuggestedImportance,
EvidenceScenes = candidate.EvidenceScenes
};
}
return candidate;
}).ToList();
return new CoreImportCharacterCandidateResolutionResult
{
Candidates = output,
AutoResolvedCount = resolved
};
}
}