PlotDirector/PlotLine/Data/StoryIntelligenceIllustrationMatchingRepository.cs

118 lines
5.9 KiB
C#

using Dapper;
using PlotLine.Models;
namespace PlotLine.Data;
public interface IStoryIntelligenceIllustrationMatchingRepository
{
Task<IReadOnlyList<StoryIntelligenceCharacterIllustrationAssignment>> ListAssignmentsAsync(int projectId);
Task<StoryIntelligenceCharacterIllustrationAssignment> UpsertAssignmentAsync(StoryIntelligenceCharacterIllustrationAssignmentSave request);
Task<StoryIntelligenceIllustrationDemand> UpsertDemandAsync(StoryIntelligenceIllustrationDemandRequest request);
}
public sealed class StoryIntelligenceIllustrationMatchingRepository(ISqlConnectionFactory connectionFactory) : IStoryIntelligenceIllustrationMatchingRepository
{
public async Task<IReadOnlyList<StoryIntelligenceCharacterIllustrationAssignment>> ListAssignmentsAsync(int projectId)
{
using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<StoryIntelligenceCharacterIllustrationAssignment>(
"""
SELECT
StoryIntelligenceCharacterIllustrationAssignmentID,
ProjectID,
CharacterKey,
CharacterName,
IllustrationLibraryItemID,
StableCode,
MatchConfidence,
MatchingScore,
CAST(NULL AS nvarchar(max)) AS EvidenceJson,
CAST(NULL AS nvarchar(max)) AS CandidateDiagnosticsJson,
ReasonChosen,
ReasonReassigned,
IsActive,
CreatedUtc,
UpdatedUtc,
AssignmentStatus,
AssignedUtc,
LastValidatedUtc,
EvidenceVersion,
IsFallback
FROM dbo.StoryIntelligenceCharacterIllustrationAssignments
WHERE ProjectID = @ProjectID
AND IsActive = 1;
""",
new { ProjectID = projectId });
return rows.ToList();
}
public async Task<StoryIntelligenceCharacterIllustrationAssignment> UpsertAssignmentAsync(StoryIntelligenceCharacterIllustrationAssignmentSave request)
{
using var connection = connectionFactory.CreateConnection();
return await connection.QuerySingleAsync<StoryIntelligenceCharacterIllustrationAssignment>(
"""
SET XACT_ABORT ON;
MERGE dbo.StoryIntelligenceCharacterIllustrationAssignments WITH (HOLDLOCK) AS target
USING (SELECT @ProjectID AS ProjectID, @CharacterKey AS CharacterKey) AS source
ON target.ProjectID = source.ProjectID
AND target.CharacterKey = source.CharacterKey
AND target.IsActive = 1
WHEN MATCHED THEN
UPDATE SET
CharacterName = @CharacterName,
IllustrationLibraryItemID = @IllustrationLibraryItemID,
StableCode = @StableCode,
MatchConfidence = @MatchConfidence,
MatchingScore = @MatchingScore,
EvidenceJson = @EvidenceJson,
CandidateDiagnosticsJson = @CandidateDiagnosticsJson,
ReasonChosen = @ReasonChosen,
ReasonReassigned = @ReasonReassigned,
AssignmentStatus = CASE WHEN @IllustrationLibraryItemID IS NULL THEN N'Fallback' ELSE N'Assigned' END,
LastValidatedUtc = SYSUTCDATETIME(),
EvidenceVersion = N'21K',
IsFallback = CASE WHEN @IllustrationLibraryItemID IS NULL THEN 1 ELSE 0 END,
UpdatedUtc = SYSUTCDATETIME()
WHEN NOT MATCHED THEN
INSERT (ProjectID, CharacterKey, CharacterName, IllustrationLibraryItemID, StableCode, MatchConfidence, MatchingScore, EvidenceJson, CandidateDiagnosticsJson, ReasonChosen, ReasonReassigned, AssignmentStatus, AssignedUtc, LastValidatedUtc, EvidenceVersion, IsFallback)
VALUES (@ProjectID, @CharacterKey, @CharacterName, @IllustrationLibraryItemID, @StableCode, @MatchConfidence, @MatchingScore, @EvidenceJson, @CandidateDiagnosticsJson, @ReasonChosen, @ReasonReassigned, CASE WHEN @IllustrationLibraryItemID IS NULL THEN N'Fallback' ELSE N'Assigned' END, SYSUTCDATETIME(), SYSUTCDATETIME(), N'21K', CASE WHEN @IllustrationLibraryItemID IS NULL THEN 1 ELSE 0 END);
SELECT *
FROM dbo.StoryIntelligenceCharacterIllustrationAssignments
WHERE ProjectID = @ProjectID
AND CharacterKey = @CharacterKey
AND IsActive = 1;
""",
request);
}
public async Task<StoryIntelligenceIllustrationDemand> UpsertDemandAsync(StoryIntelligenceIllustrationDemandRequest request)
{
using var connection = connectionFactory.CreateConnection();
return await connection.QuerySingleAsync<StoryIntelligenceIllustrationDemand>(
"""
SET XACT_ABORT ON;
MERGE dbo.StoryIntelligenceIllustrationDemands WITH (HOLDLOCK) AS target
USING (SELECT @ProjectID AS ProjectID, @DemandKey AS DemandKey) AS source
ON ISNULL(target.ProjectID, -1) = ISNULL(source.ProjectID, -1)
AND target.DemandKey = source.DemandKey
WHEN MATCHED THEN
UPDATE SET
RequestCount = RequestCount + 1,
LastRequestedUtc = SYSUTCDATETIME(),
UpdatedUtc = SYSUTCDATETIME()
WHEN NOT MATCHED THEN
INSERT (ProjectID, DemandKey, AgeBand, Presentation, HairColour, SkinTone, HairLength, Glasses, FacialHair)
VALUES (@ProjectID, @DemandKey, @AgeBand, @Presentation, @HairColour, @SkinTone, @HairLength, @Glasses, @FacialHair);
SELECT *
FROM dbo.StoryIntelligenceIllustrationDemands
WHERE ISNULL(ProjectID, -1) = ISNULL(@ProjectID, -1)
AND DemandKey = @DemandKey;
""",
request);
}
}