using System.Data; using Dapper; using PlotLine.Models; namespace PlotLine.Data; public interface IManuscriptTextStatisticsRepository { Task SaveAsync(int sceneId, ManuscriptTextStatistics statistics); Task GetBySceneAsync(int sceneId); Task> ListByChapterAsync(int chapterId); Task GetSourceBySceneAsync(int sceneId); } public sealed class ManuscriptTextStatisticsRepository(ISqlConnectionFactory connectionFactory) : IManuscriptTextStatisticsRepository { public async Task SaveAsync(int sceneId, ManuscriptTextStatistics statistics) { using var connection = connectionFactory.CreateConnection(); await connection.ExecuteAsync( "dbo.SceneTextStatistics_Save", new { SceneID = sceneId, statistics.TotalWordCount, statistics.DialogueWordCount, statistics.ProseWordCount, statistics.TotalParagraphCount, statistics.DialogueParagraphCount, statistics.ProseParagraphCount }, commandType: CommandType.StoredProcedure); } public async Task GetBySceneAsync(int sceneId) { using var connection = connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync( "dbo.SceneTextStatistics_GetByScene", new { SceneID = sceneId }, commandType: CommandType.StoredProcedure); } public async Task> ListByChapterAsync(int chapterId) { using var connection = connectionFactory.CreateConnection(); var rows = await connection.QueryAsync( "dbo.SceneTextStatistics_ListByChapter", new { ChapterID = chapterId }, commandType: CommandType.StoredProcedure); return rows.ToDictionary(row => row.SceneID, row => new ManuscriptTextStatistics { TotalWordCount = row.TotalWordCount, DialogueWordCount = row.DialogueWordCount, ProseWordCount = row.ProseWordCount, TotalParagraphCount = row.TotalParagraphCount, DialogueParagraphCount = row.DialogueParagraphCount, ProseParagraphCount = row.ProseParagraphCount }); } public async Task GetSourceBySceneAsync(int sceneId) { using var connection = connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync( "dbo.SceneManuscriptSource_GetByScene", new { SceneID = sceneId }, commandType: CommandType.StoredProcedure); } private sealed class SceneTextStatisticsRow { public int SceneID { get; init; } public int TotalWordCount { get; init; } public int DialogueWordCount { get; init; } public int ProseWordCount { get; init; } public int TotalParagraphCount { get; init; } public int DialogueParagraphCount { get; init; } public int ProseParagraphCount { get; init; } } }