Skip to content

Commit 23c25d1

Browse files
committed
feat: add support for merging side/main stories
Added **EXPERIMENTAL** support for merging side/main stories… making the existing merge logic even more complex in the process.
1 parent f9c7351 commit 23c25d1

File tree

2 files changed

+96
-56
lines changed

2 files changed

+96
-56
lines changed

Shokofin/API/ShokoAPIManager.cs

+95-56
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,16 @@ seriesType is not SeriesType.Unknown
172172
else if (tags.ContainsKey("/tmdb structure"))
173173
seriesSettings.StructureType = SeriesStructureType.TMDB_SeriesAndMovies;
174174

175-
if (tags.ContainsKey("/no merge")) {
176-
seriesSettings.MergeOverride |= SeriesMergingOverride.NoMerge;
177-
}
178-
else {
179-
if (tags.ContainsKey("/merge forward"))
180-
seriesSettings.MergeOverride |= SeriesMergingOverride.MergeForward;
181-
if (tags.ContainsKey("/merge backward"))
182-
seriesSettings.MergeOverride |= SeriesMergingOverride.MergeBackward;
183-
}
175+
if (tags.ContainsKey("/no merge"))
176+
seriesSettings.MergeOverride = SeriesMergingOverride.NoMerge;
177+
else if (tags.ContainsKey("/merge with main story"))
178+
seriesSettings.MergeOverride = SeriesMergingOverride.MergeWithMainStory;
179+
else if (tags.ContainsKey("/merge forward") && tags.ContainsKey("/merge backward"))
180+
seriesSettings.MergeOverride = SeriesMergingOverride.MergeForward | SeriesMergingOverride.MergeBackward;
181+
else if (tags.ContainsKey("/merge forward"))
182+
seriesSettings.MergeOverride = SeriesMergingOverride.MergeForward;
183+
else if (tags.ContainsKey("/merge backward"))
184+
seriesSettings.MergeOverride = SeriesMergingOverride.MergeBackward;
184185

185186
if (tags.ContainsKey("/episodes as specials")) {
186187
seriesSettings.EpisodesAsSpecials = true;
@@ -1267,12 +1268,17 @@ private async Task<SeasonInfo> CreateSeasonInfo(ShokoSeries series) {
12671268
var currentDate = currentSeries.AniDB.AirDate.Value;
12681269
var currentRelations = relations;
12691270
var currentConfig = seriesConfig;
1271+
var groupId = currentSeries.IDs.ParentGroup;
12701272
while (currentRelations.Count > 0) {
1271-
foreach (var prequelRelation in currentRelations.Where(relation => relation.Type is RelationType.Prequel && relation.RelatedIDs.Shoko.HasValue)) {
1273+
foreach (
1274+
var prequelRelation in currentRelations
1275+
.Where(relation => relation.Type is RelationType.Prequel or RelationType.MainStory && relation.RelatedIDs.Shoko.HasValue)
1276+
.OrderBy(relation => relation.Type is RelationType.Prequel)
1277+
) {
12721278
if (await ApiClient.GetShokoSeries(prequelRelation.RelatedIDs.Shoko!.Value.ToString()).ConfigureAwait(false) is not { } prequelSeries)
12731279
continue;
12741280

1275-
if (prequelSeries.IDs.ParentGroup != currentSeries.IDs.ParentGroup)
1281+
if (prequelSeries.IDs.ParentGroup != groupId)
12761282
continue;
12771283

12781284
var prequelConfig = await GetSeriesConfiguration(prequelSeries.Id).ConfigureAwait(false);
@@ -1285,10 +1291,14 @@ private async Task<SeasonInfo> CreateSeasonInfo(ShokoSeries series) {
12851291
if (!config.EXPERIMENTAL_MergeSeasonsTypes.Contains(prequelConfig.TypeOverride ?? prequelSeries.AniDB.Type))
12861292
continue;
12871293

1288-
if (prequelSeries.AniDB.AirDate is not { } prequelDate || prequelDate > currentDate)
1294+
if (prequelSeries.AniDB.AirDate is not { } prequelDate || (prequelRelation.Type is RelationType.Prequel && prequelDate > currentDate))
12891295
continue;
12901296

1291-
var mergeOverride = currentConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeBackward) || prequelConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeForward);
1297+
var mergeOverride = (
1298+
prequelRelation.Type is RelationType.Prequel && (currentConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeBackward) || prequelConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeForward))
1299+
) || (
1300+
prequelRelation.Type is RelationType.MainStory && currentConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeWithMainStory)
1301+
);
12921302
if (!mergeOverride) {
12931303
if (maxDaysThreshold is -1)
12941304
continue;
@@ -1311,6 +1321,10 @@ private async Task<SeasonInfo> CreateSeasonInfo(ShokoSeries series) {
13111321
goto continuePrequelWhileLoop;
13121322
}
13131323

1324+
// We only want to merge main/side stories if the override is set.
1325+
if (prequelRelation.Type is RelationType.MainStory)
1326+
continue;
1327+
13141328
if (string.IsNullOrEmpty(adjustedPrequelMainTitle)) {
13151329
if (string.Equals(adjustedMainTitle, prequelMainTitle, StringComparison.InvariantCultureIgnoreCase)) {
13161330
currentSeries = prequelSeries;
@@ -1345,63 +1359,88 @@ private async Task<SeasonInfo> CreateSeasonInfo(ShokoSeries series) {
13451359
goto logAndReturn;
13461360
}
13471361

1348-
while (currentRelations.Count > 0) {
1349-
foreach (var sequelRelation in currentRelations.Where(relation => relation.Type == RelationType.Sequel && relation.RelatedIDs.Shoko.HasValue)) {
1350-
if (await ApiClient.GetShokoSeries(sequelRelation.RelatedIDs.Shoko!.Value.ToString()).ConfigureAwait(false) is not { } sequelSeries)
1351-
continue;
1352-
1353-
if (sequelSeries.IDs.ParentGroup != currentSeries.IDs.ParentGroup)
1354-
continue;
1362+
var storyStack = new Stack<(string adjustedMainTitle, DateTime currentDate, SeriesConfiguration currentConfig, IReadOnlyList<Relation> currentRelations, int relationOffset)>([
1363+
(adjustedMainTitle, currentDate, currentConfig, currentRelations, 0)
1364+
]);
1365+
while (storyStack.Count > 0) {
1366+
(adjustedMainTitle, currentDate, currentConfig, currentRelations, var relationOffset) = storyStack.Pop();
1367+
while (currentRelations.Count > 0) {
1368+
foreach (
1369+
var sequelRelation in currentRelations
1370+
.Where(relation => relation.Type is RelationType.Sequel or RelationType.SideStory && relation.RelatedIDs.Shoko.HasValue)
1371+
.OrderBy(relation => relation.Type is RelationType.Sequel)
1372+
.Skip(relationOffset)
1373+
) {
1374+
relationOffset++;
1375+
if (await ApiClient.GetShokoSeries(sequelRelation.RelatedIDs.Shoko!.Value.ToString()).ConfigureAwait(false) is not { } sequelSeries)
1376+
continue;
13551377

1356-
var sequelConfig = await GetSeriesConfiguration(sequelSeries.Id).ConfigureAwait(false);
1357-
if (sequelConfig.MergeOverride is SeriesMergingOverride.NoMerge)
1358-
continue;
1378+
if (sequelSeries.IDs.ParentGroup != groupId)
1379+
continue;
13591380

1360-
if (sequelConfig.StructureType is not SeriesStructureType.Shoko_Groups)
1361-
continue;
1381+
var sequelConfig = await GetSeriesConfiguration(sequelSeries.Id).ConfigureAwait(false);
1382+
if (sequelConfig.MergeOverride is SeriesMergingOverride.NoMerge)
1383+
continue;
13621384

1363-
if (!config.EXPERIMENTAL_MergeSeasonsTypes.Contains(sequelConfig.TypeOverride ?? sequelSeries.AniDB.Type))
1364-
continue;
1385+
if (sequelConfig.StructureType is not SeriesStructureType.Shoko_Groups)
1386+
continue;
13651387

1366-
if (sequelSeries.AniDB.AirDate is not { } sequelDate || sequelDate < currentDate)
1367-
continue;
1388+
if (!config.EXPERIMENTAL_MergeSeasonsTypes.Contains(sequelConfig.TypeOverride ?? sequelSeries.AniDB.Type))
1389+
continue;
13681390

1369-
var mergeOverride = currentConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeForward) || sequelConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeBackward);
1370-
if (!mergeOverride) {
1371-
if (maxDaysThreshold < 0)
1391+
if (sequelSeries.AniDB.AirDate is not { } sequelDate || (sequelRelation.Type is RelationType.Sequel && sequelDate < currentDate))
13721392
continue;
13731393

1374-
if (maxDaysThreshold > 0) {
1375-
var deltaDays = (int)Math.Floor((sequelDate - currentDate).TotalDays);
1376-
if (deltaDays > maxDaysThreshold)
1394+
var mergeOverride = (
1395+
sequelRelation.Type is RelationType.Sequel && (currentConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeForward) || sequelConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeBackward))
1396+
) || (
1397+
sequelRelation.Type is RelationType.SideStory && sequelConfig.MergeOverride.HasFlag(SeriesMergingOverride.MergeWithMainStory)
1398+
);
1399+
if (!mergeOverride) {
1400+
if (maxDaysThreshold < 0)
13771401
continue;
1402+
1403+
if (maxDaysThreshold > 0) {
1404+
var deltaDays = (int)Math.Floor((sequelDate - currentDate).TotalDays);
1405+
if (deltaDays > maxDaysThreshold)
1406+
continue;
1407+
}
13781408
}
1379-
}
13801409

1381-
var sequelMainTitle = sequelSeries.AniDB.Titles.First(title => title.Type == TitleType.Main).Value;
1382-
var adjustedSequelMainTitle = AdjustMainTitle(sequelMainTitle);
1383-
if (mergeOverride) {
1384-
adjustedMainTitle = adjustedSequelMainTitle ?? sequelMainTitle;
1385-
extraIds.Add(sequelSeries.Id);
1386-
currentSeries = sequelSeries;
1387-
currentDate = sequelDate;
1388-
currentRelations = await ApiClient.GetRelationsForShokoSeries(sequelSeries.Id).ConfigureAwait(false);
1389-
currentConfig = sequelConfig;
1390-
goto continueSequelWhileLoop;
1391-
}
1410+
var sequelMainTitle = sequelSeries.AniDB.Titles.First(title => title.Type == TitleType.Main).Value;
1411+
var adjustedSequelMainTitle = AdjustMainTitle(sequelMainTitle);
1412+
if (mergeOverride) {
1413+
// If we're about to enter a side story, then push the main story on the stack at the next relation index.
1414+
if (sequelRelation.Type is RelationType.SideStory)
1415+
storyStack.Push((adjustedMainTitle, currentDate, currentConfig, currentRelations, relationOffset));
1416+
1417+
// Re-focus on the sequel when overriding.
1418+
adjustedMainTitle = adjustedSequelMainTitle ?? sequelMainTitle;
1419+
extraIds.Add(sequelSeries.Id);
1420+
currentDate = sequelDate;
1421+
currentRelations = await ApiClient.GetRelationsForShokoSeries(sequelSeries.Id).ConfigureAwait(false);
1422+
currentConfig = sequelConfig;
1423+
goto continueSequelWhileLoop;
1424+
}
13921425

1393-
if (string.IsNullOrEmpty(adjustedSequelMainTitle))
1394-
continue;
1426+
// We only want to merge main/side stories if the override is set.
1427+
if (sequelRelation.Type is RelationType.SideStory)
1428+
continue;
13951429

1396-
if (string.Equals(adjustedMainTitle, adjustedSequelMainTitle, StringComparison.InvariantCultureIgnoreCase)) {
1397-
extraIds.Add(sequelSeries.Id);
1398-
currentDate = sequelDate;
1399-
currentRelations = await ApiClient.GetRelationsForShokoSeries(sequelSeries.Id).ConfigureAwait(false);
1400-
goto continueSequelWhileLoop;
1430+
if (string.IsNullOrEmpty(adjustedSequelMainTitle))
1431+
continue;
1432+
1433+
if (string.Equals(adjustedMainTitle, adjustedSequelMainTitle, StringComparison.InvariantCultureIgnoreCase)) {
1434+
extraIds.Add(sequelSeries.Id);
1435+
currentDate = sequelDate;
1436+
currentRelations = await ApiClient.GetRelationsForShokoSeries(sequelSeries.Id).ConfigureAwait(false);
1437+
currentConfig = sequelConfig;
1438+
goto continueSequelWhileLoop;
1439+
}
14011440
}
1441+
break;
1442+
continueSequelWhileLoop: continue;
14021443
}
1403-
break;
1404-
continueSequelWhileLoop: continue;
14051444
}
14061445

14071446
logAndReturn:

Shokofin/Configuration/SeriesMergingOverride.cs

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ public enum SeriesMergingOverride {
99
NoMerge = 1,
1010
MergeForward = 2,
1111
MergeBackward = 4,
12+
MergeWithMainStory = 8,
1213
}

0 commit comments

Comments
 (0)