171 lines
6.7 KiB
C#
171 lines
6.7 KiB
C#
using System.Data;
|
|
using Dapper;
|
|
using PlotLine.Models;
|
|
|
|
namespace PlotLine.Data;
|
|
|
|
public interface IStoryIntelligenceResultRepository
|
|
{
|
|
Task<int> SaveAsync(StoryIntelligenceRunSaveRequest request);
|
|
Task<IReadOnlyList<StoryIntelligenceSavedRunListItem>> ListRunsAsync();
|
|
Task<StoryIntelligenceSavedRun?> GetRunAsync(int runId);
|
|
Task<StoryIntelligenceSavedChapterResult?> GetChapterResultAsync(int runId);
|
|
Task<IReadOnlyList<StoryIntelligenceSavedSceneResult>> ListSceneResultsAsync(int runId);
|
|
}
|
|
|
|
public sealed class StoryIntelligenceResultRepository(ISqlConnectionFactory connectionFactory) : IStoryIntelligenceResultRepository
|
|
{
|
|
public async Task<int> SaveAsync(StoryIntelligenceRunSaveRequest request)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
connection.Open();
|
|
using var transaction = connection.BeginTransaction();
|
|
|
|
try
|
|
{
|
|
var runId = await connection.QuerySingleAsync<int>(
|
|
"dbo.StoryIntelligenceRun_Save",
|
|
new
|
|
{
|
|
request.UserID,
|
|
request.ProjectID,
|
|
request.BookID,
|
|
request.Status,
|
|
request.SourceType,
|
|
request.SourceFileName,
|
|
request.SourceFileSizeBytes,
|
|
request.SourceWordCount,
|
|
request.SourceCharacterCount,
|
|
request.SourceChapterCount,
|
|
request.SourceDetectedImagesCount,
|
|
request.SourceDetectedTablesCount,
|
|
request.SourceDetectedFootnotesCount,
|
|
request.SourceDetectedCommentsCount,
|
|
request.PromptVersion,
|
|
request.Model,
|
|
request.StartedUtc,
|
|
request.CompletedUtc,
|
|
request.FailureStage,
|
|
request.TotalInputTokens,
|
|
request.TotalOutputTokens,
|
|
request.TotalTokens,
|
|
request.TotalDurationMs,
|
|
request.EstimatedCostGBP,
|
|
request.EstimatedCostUSD,
|
|
request.PromptVersionsSummary,
|
|
request.ErrorMessage,
|
|
request.ErrorDetail
|
|
},
|
|
transaction,
|
|
commandType: CommandType.StoredProcedure);
|
|
|
|
int? chapterResultId = null;
|
|
if (request.ChapterResult is not null)
|
|
{
|
|
var chapter = request.ChapterResult;
|
|
chapterResultId = await connection.QuerySingleAsync<int>(
|
|
"dbo.StoryIntelligenceChapterResult_Save",
|
|
new
|
|
{
|
|
StoryIntelligenceRunID = runId,
|
|
chapter.ProjectID,
|
|
chapter.BookID,
|
|
chapter.ChapterID,
|
|
chapter.ChapterNumber,
|
|
chapter.SourceLabel,
|
|
chapter.PromptVersion,
|
|
chapter.Model,
|
|
chapter.RawResponseJson,
|
|
chapter.OutputTextJson,
|
|
chapter.ParsedJson,
|
|
chapter.ValidationErrorsCount,
|
|
chapter.ValidationWarningsCount,
|
|
chapter.InputTokens,
|
|
chapter.OutputTokens,
|
|
chapter.TotalTokens,
|
|
chapter.DurationMs
|
|
},
|
|
transaction,
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
foreach (var scene in request.SceneResults)
|
|
{
|
|
await connection.ExecuteAsync(
|
|
"dbo.StoryIntelligenceSceneResult_Save",
|
|
new
|
|
{
|
|
StoryIntelligenceRunID = runId,
|
|
ChapterResultID = chapterResultId,
|
|
scene.ProjectID,
|
|
scene.BookID,
|
|
scene.ChapterID,
|
|
scene.SceneID,
|
|
scene.TemporarySceneNumber,
|
|
scene.StartParagraph,
|
|
scene.EndParagraph,
|
|
scene.SourceLabel,
|
|
scene.PromptVersion,
|
|
scene.Model,
|
|
scene.RawResponseJson,
|
|
scene.OutputTextJson,
|
|
scene.ParsedJson,
|
|
scene.ValidationErrorsCount,
|
|
scene.ValidationWarningsCount,
|
|
scene.InputTokens,
|
|
scene.OutputTokens,
|
|
scene.TotalTokens,
|
|
scene.DurationMs
|
|
},
|
|
transaction,
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
transaction.Commit();
|
|
return runId;
|
|
}
|
|
catch
|
|
{
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<IReadOnlyList<StoryIntelligenceSavedRunListItem>> ListRunsAsync()
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
var rows = await connection.QueryAsync<StoryIntelligenceSavedRunListItem>(
|
|
"dbo.StoryIntelligenceRun_ListAdmin",
|
|
commandType: CommandType.StoredProcedure);
|
|
return rows.ToList();
|
|
}
|
|
|
|
public async Task<StoryIntelligenceSavedRun?> GetRunAsync(int runId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleOrDefaultAsync<StoryIntelligenceSavedRun>(
|
|
"dbo.StoryIntelligenceRun_GetAdmin",
|
|
new { StoryIntelligenceRunID = runId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<StoryIntelligenceSavedChapterResult?> GetChapterResultAsync(int runId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleOrDefaultAsync<StoryIntelligenceSavedChapterResult>(
|
|
"dbo.StoryIntelligenceChapterResult_GetByRun",
|
|
new { StoryIntelligenceRunID = runId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<StoryIntelligenceSavedSceneResult>> ListSceneResultsAsync(int runId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
var rows = await connection.QueryAsync<StoryIntelligenceSavedSceneResult>(
|
|
"dbo.StoryIntelligenceSceneResult_ListByRun",
|
|
new { StoryIntelligenceRunID = runId },
|
|
commandType: CommandType.StoredProcedure);
|
|
return rows.ToList();
|
|
}
|
|
}
|