Skip to content

Commit

Permalink
refactor: improve matcher algorithm for some edge cases
Browse files Browse the repository at this point in the history
- Add direct return for single video and subtitle match
- Implement merging of items with the same filename
- Add unit test for MergeSameFilenameItems function
  • Loading branch information
qwqcode committed Nov 14, 2024
1 parent 5eb0512 commit d229f38
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
19 changes: 17 additions & 2 deletions SubRenamer.Core/Matcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,27 @@ public static List<MatchItem> Execute(IReadOnlyList<MatchItem> inputItems, Match
subtitleFiles.Add(item.Subtitle);
});

// Return directly if only 1 video and 1 subtitle
if (videoFiles.Count == 1 && subtitleFiles.Count == 1)
return [new MatchItem("1", videoFiles[0], subtitleFiles[0])];

// Get file keys
var video2Keys = CalculateFileKeys(videoFiles, customRegex: options.VideoRegex);
var subtitle2Keys = CalculateFileKeys(subtitleFiles, customRegex: options.SubtitleRegex);

// Merge items with same filename
result = MatcherHelper.MergeSameFilenameItems(result);

// Apply keys
List<MatchItem> keyedItems = [];
foreach (var item in result)
{
if (item.Key != "")
{
keyedItems.Add(item);
continue;
}

string? k = null;

if (!string.IsNullOrEmpty(item.Video)) video2Keys.TryGetValue(item.Video, out k);
Expand Down Expand Up @@ -77,15 +90,17 @@ private static Dictionary<string, string> CalculateFileKeys(IReadOnlyList<string
// Extract Match keys
foreach (var f in files)
{
result[f] = MatcherHelper.PatchKey(MatcherDiff.ExtractMatchKeyByDiff(diff, Path.GetFileNameWithoutExtension(f)));
result[f] = MatcherHelper.PatchKey(
MatcherDiff.ExtractMatchKeyByDiff(diff, Path.GetFileNameWithoutExtension(f)));
}
}
else
{
// Method 2. Custom Regex
foreach (var f in files)
{
result[f] = MatcherHelper.PatchKey(MatcherHelper.ExtractMatchKeyRegex(customRegex, Path.GetFileName(f)));
result[f] = MatcherHelper.PatchKey(
MatcherHelper.ExtractMatchKeyRegex(customRegex, Path.GetFileName(f)));
}
}

Expand Down
37 changes: 37 additions & 0 deletions SubRenamer.Core/MatcherHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,43 @@ public static List<MatchItem> MergeSameKeysItems(IReadOnlyList<MatchItem> items)
return result;
}

public static List<MatchItem> MergeSameFilenameItems(IReadOnlyList<MatchItem> items)
{
var groupBNotNullCNull = items
.Where(item => string.IsNullOrEmpty(item.Key) && !string.IsNullOrEmpty(item.Video) && string.IsNullOrEmpty(item.Subtitle))
.ToList();

var groupBNullCNotNull = items
.Where(item => string.IsNullOrEmpty(item.Key) && string.IsNullOrEmpty(item.Video) && !string.IsNullOrEmpty(item.Subtitle))
.ToList();

var result = new List<MatchItem>();

var mergedItems = groupBNotNullCNull
.Join(groupBNullCNotNull,
item1 => Path.GetFileNameWithoutExtension(item1.Video),
item2 => Path.GetFileNameWithoutExtension(item2.Subtitle),
(item1, item2) => new MatchItem(Path.GetFileNameWithoutExtension(item1.Video), item1.Video, item2.Subtitle))
.ToList();

result.AddRange(mergedItems);

var mergedVideos = new HashSet<string>(mergedItems.Select(x => x.Video));
var mergedSubtitles = new HashSet<string>(mergedItems.Select(x => x.Subtitle));

var itemsToRemove = items.Where(item =>
{
if (item.Key != "") return false;
if (item.Video != "" && item.Subtitle != "") return false;
if (item.Video != "" && mergedVideos.Contains(item.Video)) return true;
if (item.Subtitle != "" && mergedSubtitles.Contains(item.Subtitle)) return true;
return false;
});
result.AddRange(items.Where(item => !itemsToRemove.Contains(item)));

return result;
}

public static List<MatchItem> MoveEmptyKeyItemsToLast(IReadOnlyList<MatchItem> items)
{
var keyedItems = items.Where(x => !string.IsNullOrEmpty(x.Key));
Expand Down
40 changes: 40 additions & 0 deletions SubRenamer.Tests/MatcherTests/MergeSameFilenameItemsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using SubRenamer.Core;
using static SubRenamer.Core.MatcherHelper;

namespace SubRenamer.Tests.MatcherTests;

[TestFixture]
public class MergeSameFilenameItemsTests
{
[Test]
public void Basic()
{
var input = new List<MatchItem>
{
new("", "a.mp4", ""),
new("", "", "b.srt"),

new("", "", "a.srt"),
new("", "b.mp4", ""),


new("", "v1.mp4", ""),
new("", "", "s1.srt"),
new("2", "v2.mp4", ""),
new("2", "", "s2.srt"),
};
var output = new List<MatchItem>
{
new("a", "a.mp4", "a.srt"),
new("b", "b.mp4", "b.srt"),

new("", "v1.mp4", ""),
new("", "", "s1.srt"),
new("2", "v2.mp4", ""),
new("2", "", "s2.srt"),
};

var result = MergeSameFilenameItems(input);
Assert.That(result, Is.EqualTo(output));
}
}

0 comments on commit d229f38

Please sign in to comment.