PlotDirector/PlotLine/Sql/029_ProjectSceneMetricsManagement.sql
2026-06-03 15:55:21 +01:00

431 lines
15 KiB
Transact-SQL

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_ProjectHasMetrics
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT CAST(CASE WHEN EXISTS
(
SELECT 1
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID AND mt.IsActive = 1
) THEN 1 ELSE 0 END AS bit);
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_AddMissingDefaultsForProject
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID)
BEGIN
INSERT dbo.ProjectTimelineSettings
(ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings)
VALUES
(@ProjectID, 1, 1, 1, 1, 1, 1);
END;
INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
FROM dbo.SceneMetricTypes mt
WHERE mt.ProjectID IS NULL
AND mt.IsActive = 1
AND mt.MetricName IN
(
N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action', N'Darkness',
N'Romance', N'Sexual Charge', N'Violence', N'Hope / Lightness', N'Comedy', N'Mystery'
)
AND NOT EXISTS
(
SELECT 1
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN dbo.SceneMetricTypes existing ON existing.MetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND LOWER(existing.MetricName) = LOWER(mt.MetricName)
);
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_ListForProjectManagement
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
;WITH CandidateMetrics AS
(
SELECT mt.*
FROM dbo.SceneMetricTypes mt
WHERE mt.ProjectID = @ProjectID
UNION
SELECT mt.*
FROM dbo.SceneMetricTypes mt
WHERE mt.ProjectID IS NULL
AND mt.MetricName IN
(
N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action', N'Darkness',
N'Romance', N'Sexual Charge', N'Violence', N'Hope / Lightness', N'Comedy', N'Mystery'
)
UNION
SELECT mt.*
FROM dbo.SceneMetricTypes mt
INNER JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.MetricTypeID = mt.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
)
SELECT cm.MetricTypeID, cm.ProjectID, cm.MetricName, cm.Description, cm.MinValue, cm.MaxValue, cm.DefaultValue,
COALESCE(ptms.SortOrder, cm.SortOrder) AS SortOrder,
CAST(CASE WHEN cm.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsActive,
CAST(CASE WHEN cm.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsEnabledForProject,
COUNT(smv.SceneID) AS ValueCount
FROM CandidateMetrics cm
LEFT JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = cm.MetricTypeID
LEFT JOIN dbo.SceneMetricValues smv ON smv.MetricTypeID = cm.MetricTypeID
GROUP BY cm.MetricTypeID, cm.ProjectID, cm.MetricName, cm.Description, cm.MinValue, cm.MaxValue, cm.DefaultValue,
cm.SortOrder, cm.IsActive, ptms.MetricTypeID, ptms.SortOrder
ORDER BY
CASE WHEN cm.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 0 ELSE 1 END,
COALESCE(ptms.SortOrder, cm.SortOrder),
cm.MetricName;
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_GetForProject
@MetricTypeID int,
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName, mt.Description, mt.MinValue, mt.MaxValue, mt.DefaultValue,
COALESCE(ptms.SortOrder, mt.SortOrder) AS SortOrder,
CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsActive,
CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsEnabledForProject,
(SELECT COUNT(*) FROM dbo.SceneMetricValues smv WHERE smv.MetricTypeID = mt.MetricTypeID) AS ValueCount
FROM dbo.SceneMetricTypes mt
LEFT JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = mt.MetricTypeID
WHERE mt.MetricTypeID = @MetricTypeID
AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID);
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_SaveForProject
@MetricTypeID int = NULL,
@ProjectID int,
@MetricName nvarchar(100),
@Description nvarchar(500) = NULL,
@MinValue int,
@MaxValue int,
@DefaultValue int,
@SortOrder int,
@IsActive bit = 1
AS
BEGIN
SET NOCOUNT ON;
IF @MinValue >= @MaxValue
THROW 50010, 'Metric minimum must be less than maximum.', 1;
IF @DefaultValue < @MinValue OR @DefaultValue > @MaxValue
THROW 50011, 'Metric default value must be inside the metric range.', 1;
IF @MetricTypeID IS NULL OR @MetricTypeID = 0
BEGIN
SELECT @MetricTypeID = MetricTypeID
FROM dbo.SceneMetricTypes
WHERE ProjectID = @ProjectID AND LOWER(MetricName) = LOWER(@MetricName);
IF @MetricTypeID IS NULL OR @MetricTypeID = 0
BEGIN
INSERT dbo.SceneMetricTypes (ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive)
VALUES (@ProjectID, @MetricName, @Description, @MinValue, @MaxValue, @DefaultValue, @SortOrder, 1);
SET @MetricTypeID = CAST(SCOPE_IDENTITY() AS int);
END
END
UPDATE dbo.SceneMetricTypes
SET MetricName = @MetricName,
Description = @Description,
MinValue = @MinValue,
MaxValue = @MaxValue,
DefaultValue = @DefaultValue,
SortOrder = @SortOrder,
IsActive = 1
WHERE MetricTypeID = @MetricTypeID
AND (ProjectID = @ProjectID OR ProjectID IS NULL);
IF @IsActive = 1
BEGIN
MERGE dbo.ProjectTimelineMetricSettings AS target
USING (SELECT @ProjectID AS ProjectID, @MetricTypeID AS MetricTypeID, @SortOrder AS SortOrder) AS source
ON target.ProjectID = source.ProjectID AND target.MetricTypeID = source.MetricTypeID
WHEN MATCHED THEN UPDATE SET SortOrder = source.SortOrder
WHEN NOT MATCHED THEN INSERT (ProjectID, MetricTypeID, SortOrder) VALUES (source.ProjectID, source.MetricTypeID, source.SortOrder);
END
ELSE
BEGIN
DELETE FROM dbo.ProjectTimelineMetricSettings WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID;
END;
SELECT @MetricTypeID;
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_SetActiveForProject
@MetricTypeID int,
@ProjectID int,
@IsActive bit
AS
BEGIN
SET NOCOUNT ON;
IF @IsActive = 1
BEGIN
UPDATE dbo.SceneMetricTypes
SET IsActive = 1
WHERE MetricTypeID = @MetricTypeID
AND ProjectID = @ProjectID;
INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
FROM dbo.SceneMetricTypes mt
WHERE mt.MetricTypeID = @MetricTypeID
AND mt.IsActive = 1
AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
AND NOT EXISTS
(
SELECT 1 FROM dbo.ProjectTimelineMetricSettings ptms
WHERE ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = @MetricTypeID
);
SELECT CAST(CASE WHEN EXISTS
(
SELECT 1
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND ptms.MetricTypeID = @MetricTypeID
AND mt.IsActive = 1
AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
) THEN 1 ELSE 0 END AS bit);
RETURN;
END
ELSE
BEGIN
DELETE FROM dbo.ProjectTimelineMetricSettings
WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID;
UPDATE dbo.SceneMetricTypes
SET IsActive = 0
WHERE MetricTypeID = @MetricTypeID AND ProjectID = @ProjectID;
SELECT CAST(CASE WHEN NOT EXISTS
(
SELECT 1
FROM dbo.ProjectTimelineMetricSettings
WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID
) THEN 1 ELSE 0 END AS bit);
RETURN;
END;
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_MoveForProject
@MetricTypeID int,
@ProjectID int,
@Direction nvarchar(10)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @NormalisedDirection nvarchar(10) = CASE WHEN UPPER(@Direction) = N'UP' THEN N'Up' ELSE N'Down' END;
;WITH CandidateMetrics AS
(
SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName,
COALESCE(ptms.SortOrder, mt.SortOrder) AS SortOrder,
CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 1 ELSE 0 END AS bit) AS IsEnabledForProject,
CAST(CASE WHEN mt.IsActive = 1 AND ptms.MetricTypeID IS NOT NULL THEN 0 ELSE 1 END AS int) AS GroupRank
FROM dbo.SceneMetricTypes mt
LEFT JOIN dbo.ProjectTimelineMetricSettings ptms ON ptms.ProjectID = @ProjectID AND ptms.MetricTypeID = mt.MetricTypeID
WHERE
mt.ProjectID = @ProjectID
OR ptms.ProjectID = @ProjectID
OR
(
mt.ProjectID IS NULL
AND mt.MetricName IN
(
N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action', N'Darkness',
N'Romance', N'Sexual Charge', N'Violence', N'Hope / Lightness', N'Comedy', N'Mystery'
)
)
)
SELECT *,
ROW_NUMBER() OVER (PARTITION BY GroupRank ORDER BY SortOrder, MetricName, MetricTypeID) AS RowNumber,
ROW_NUMBER() OVER (PARTITION BY GroupRank ORDER BY SortOrder, MetricName, MetricTypeID) * 10 AS NormalisedSortOrder
INTO #OrderedMetrics
FROM CandidateMetrics;
UPDATE ptms
SET SortOrder = ordered.NormalisedSortOrder
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN #OrderedMetrics ordered ON ordered.MetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND ordered.IsEnabledForProject = 1;
UPDATE mt
SET SortOrder = ordered.NormalisedSortOrder
FROM dbo.SceneMetricTypes mt
INNER JOIN #OrderedMetrics ordered ON ordered.MetricTypeID = mt.MetricTypeID
WHERE mt.ProjectID = @ProjectID
AND ordered.IsEnabledForProject = 0;
;WITH OrderedMetrics AS
(
SELECT MetricTypeID, ProjectID, MetricName, NormalisedSortOrder AS SortOrder, IsEnabledForProject, GroupRank, RowNumber
FROM #OrderedMetrics
),
MovePair AS
(
SELECT currentMetric.MetricTypeID AS CurrentMetricTypeID,
currentMetric.ProjectID AS CurrentProjectID,
currentMetric.IsEnabledForProject AS CurrentIsEnabledForProject,
currentMetric.SortOrder AS CurrentSortOrder,
adjacentMetric.MetricTypeID AS AdjacentMetricTypeID,
adjacentMetric.ProjectID AS AdjacentProjectID,
adjacentMetric.IsEnabledForProject AS AdjacentIsEnabledForProject,
adjacentMetric.SortOrder AS AdjacentSortOrder
FROM OrderedMetrics currentMetric
INNER JOIN OrderedMetrics adjacentMetric ON adjacentMetric.GroupRank = currentMetric.GroupRank
AND adjacentMetric.RowNumber = CASE WHEN @NormalisedDirection = N'Up' THEN currentMetric.RowNumber - 1 ELSE currentMetric.RowNumber + 1 END
WHERE currentMetric.MetricTypeID = @MetricTypeID
)
SELECT *
INTO #MovePair
FROM MovePair;
IF NOT EXISTS (SELECT 1 FROM #MovePair)
BEGIN
SELECT CAST(0 AS bit);
RETURN;
END;
IF EXISTS (SELECT 1 FROM #MovePair WHERE CurrentIsEnabledForProject = 0 AND CurrentProjectID IS NULL)
BEGIN
SELECT CAST(0 AS bit);
RETURN;
END;
IF EXISTS (SELECT 1 FROM #MovePair WHERE AdjacentIsEnabledForProject = 0 AND AdjacentProjectID IS NULL)
BEGIN
SELECT CAST(0 AS bit);
RETURN;
END;
UPDATE ptms
SET SortOrder = mp.AdjacentSortOrder
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN #MovePair mp ON mp.CurrentMetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND mp.CurrentIsEnabledForProject = 1;
UPDATE mt
SET SortOrder = mp.AdjacentSortOrder
FROM dbo.SceneMetricTypes mt
INNER JOIN #MovePair mp ON mp.CurrentMetricTypeID = mt.MetricTypeID
WHERE mt.ProjectID = @ProjectID
AND mp.CurrentIsEnabledForProject = 0;
UPDATE ptms
SET SortOrder = mp.CurrentSortOrder
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN #MovePair mp ON mp.AdjacentMetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND mp.AdjacentIsEnabledForProject = 1;
UPDATE mt
SET SortOrder = mp.CurrentSortOrder
FROM dbo.SceneMetricTypes mt
INNER JOIN #MovePair mp ON mp.AdjacentMetricTypeID = mt.MetricTypeID
WHERE mt.ProjectID = @ProjectID
AND mp.AdjacentIsEnabledForProject = 0;
SELECT CAST(1 AS bit);
END;
GO
CREATE OR ALTER PROCEDURE dbo.SceneMetricType_RemoveUnusedForProject
@MetricTypeID int,
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS
(
SELECT 1
FROM dbo.SceneMetricTypes mt
WHERE mt.MetricTypeID = @MetricTypeID
AND mt.ProjectID = @ProjectID
AND mt.IsActive = 0
AND NOT EXISTS (SELECT 1 FROM dbo.SceneMetricValues smv WHERE smv.MetricTypeID = mt.MetricTypeID)
)
BEGIN
DELETE FROM dbo.ProjectTimelineMetricSettings
WHERE ProjectID = @ProjectID AND MetricTypeID = @MetricTypeID;
DELETE FROM dbo.SceneMetricTypes
WHERE MetricTypeID = @MetricTypeID AND ProjectID = @ProjectID;
SELECT CAST(1 AS bit);
RETURN;
END;
SELECT CAST(0 AS bit);
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_EnsureDefaults
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0)
RETURN;
IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID)
BEGIN
INSERT dbo.ProjectTimelineSettings
(ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings)
VALUES
(@ProjectID, 1, 1, 1, 1, 1, 1);
END;
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_MetricTypes
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT mt.MetricTypeID, mt.ProjectID, mt.MetricName, mt.Description, mt.MinValue, mt.MaxValue, mt.DefaultValue,
ptms.SortOrder, mt.IsActive
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND mt.IsActive = 1
AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
ORDER BY ptms.SortOrder, mt.SortOrder, mt.MetricName;
END;
GO