SET ANSI_NULLS ON; GO SET QUOTED_IDENTIFIER ON; GO IF OBJECT_ID(N'dbo.SceneTextStatistics', N'U') IS NULL BEGIN CREATE TABLE dbo.SceneTextStatistics ( SceneID int NOT NULL CONSTRAINT PK_SceneTextStatistics PRIMARY KEY, TotalWordCount int NOT NULL CONSTRAINT DF_SceneTextStatistics_TotalWordCount DEFAULT 0, DialogueWordCount int NOT NULL CONSTRAINT DF_SceneTextStatistics_DialogueWordCount DEFAULT 0, ProseWordCount int NOT NULL CONSTRAINT DF_SceneTextStatistics_ProseWordCount DEFAULT 0, TotalParagraphCount int NOT NULL CONSTRAINT DF_SceneTextStatistics_TotalParagraphCount DEFAULT 0, DialogueParagraphCount int NOT NULL CONSTRAINT DF_SceneTextStatistics_DialogueParagraphCount DEFAULT 0, ProseParagraphCount int NOT NULL CONSTRAINT DF_SceneTextStatistics_ProseParagraphCount DEFAULT 0, CalculatedUtc datetime2 NOT NULL CONSTRAINT DF_SceneTextStatistics_CalculatedUtc DEFAULT SYSUTCDATETIME(), UpdatedUtc datetime2 NOT NULL CONSTRAINT DF_SceneTextStatistics_UpdatedUtc DEFAULT SYSUTCDATETIME(), CONSTRAINT CK_SceneTextStatistics_NonNegative CHECK ( TotalWordCount >= 0 AND DialogueWordCount >= 0 AND ProseWordCount >= 0 AND TotalParagraphCount >= 0 AND DialogueParagraphCount >= 0 AND ProseParagraphCount >= 0 ), CONSTRAINT CK_SceneTextStatistics_WordReconciliation CHECK (DialogueWordCount + ProseWordCount = TotalWordCount), CONSTRAINT FK_SceneTextStatistics_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID) ON DELETE CASCADE ); END; GO CREATE OR ALTER PROCEDURE dbo.SceneTextStatistics_Save @SceneID int, @TotalWordCount int, @DialogueWordCount int, @ProseWordCount int, @TotalParagraphCount int, @DialogueParagraphCount int, @ProseParagraphCount int AS BEGIN SET NOCOUNT ON; IF @DialogueWordCount + @ProseWordCount <> @TotalWordCount THROW 51000, 'Dialogue and prose word counts must reconcile to the total word count.', 1; MERGE dbo.SceneTextStatistics AS target USING (SELECT @SceneID AS SceneID) AS source ON target.SceneID = source.SceneID WHEN MATCHED THEN UPDATE SET TotalWordCount = @TotalWordCount, DialogueWordCount = @DialogueWordCount, ProseWordCount = @ProseWordCount, TotalParagraphCount = @TotalParagraphCount, DialogueParagraphCount = @DialogueParagraphCount, ProseParagraphCount = @ProseParagraphCount, CalculatedUtc = SYSUTCDATETIME(), UpdatedUtc = SYSUTCDATETIME() WHEN NOT MATCHED THEN INSERT ( SceneID, TotalWordCount, DialogueWordCount, ProseWordCount, TotalParagraphCount, DialogueParagraphCount, ProseParagraphCount ) VALUES ( @SceneID, @TotalWordCount, @DialogueWordCount, @ProseWordCount, @TotalParagraphCount, @DialogueParagraphCount, @ProseParagraphCount ); END; GO CREATE OR ALTER PROCEDURE dbo.SceneTextStatistics_GetByScene @SceneID int AS BEGIN SET NOCOUNT ON; SELECT TotalWordCount, DialogueWordCount, ProseWordCount, TotalParagraphCount, DialogueParagraphCount, ProseParagraphCount FROM dbo.SceneTextStatistics WHERE SceneID = @SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneTextStatistics_ListByChapter @ChapterID int AS BEGIN SET NOCOUNT ON; SELECT stats.SceneID, stats.TotalWordCount, stats.DialogueWordCount, stats.ProseWordCount, stats.TotalParagraphCount, stats.DialogueParagraphCount, stats.ProseParagraphCount FROM dbo.SceneTextStatistics stats INNER JOIN dbo.Scenes scene ON scene.SceneID = stats.SceneID WHERE scene.ChapterID = @ChapterID AND scene.IsArchived = 0 ORDER BY scene.SortOrder, scene.SceneNumber, scene.SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneTextStatistics_ListMissingByBook @BookID int AS BEGIN SET NOCOUNT ON; SELECT source.SceneID, source.ProjectID, source.BookID, source.ChapterID, source.SourceWordCount, source.SourceCharacterCount, source.SourceKind, source.CreatedUtc, source.UpdatedUtc FROM dbo.SceneManuscriptSources source INNER JOIN dbo.Scenes scene ON scene.SceneID = source.SceneID WHERE source.BookID = @BookID AND scene.IsArchived = 0 AND NOT EXISTS ( SELECT 1 FROM dbo.SceneTextStatistics stats WHERE stats.SceneID = source.SceneID ) ORDER BY source.ChapterID, scene.SortOrder, scene.SceneNumber, scene.SceneID; END; GO