private static List <VideoInfo> GetVideosGroupedByVersion(List <VideoInfo> videos, NamingOptions namingOptions) { if (videos.Count == 0) { return(videos); } var folderName = Path.GetFileName(Path.GetDirectoryName(videos[0].Files[0].Path.AsSpan())); if (folderName.Length <= 1 || !HaveSameYear(videos)) { return(videos); } // Cannot use Span inside local functions and delegates thus we cannot use LINQ here nor merge with the above [if] for (var i = 0; i < videos.Count; i++) { var video = videos[i]; if (video.ExtraType != null) { continue; } if (!IsEligibleForMultiVersion(folderName, video.Files[0].Path, namingOptions)) { return(videos); } } // The list is created and overwritten in the caller, so we are allowed to do in-place sorting videos.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.Ordinal)); var list = new List <VideoInfo> { videos[0] }; var alternateVersionsLen = videos.Count - 1; var alternateVersions = new VideoFileInfo[alternateVersionsLen]; for (int i = 0; i < alternateVersionsLen; i++) { var video = videos[i + 1]; alternateVersions[i] = video.Files[0]; } list[0].AlternateVersions = alternateVersions; list[0].Name = folderName.ToString(); return(list); }
private IEnumerable <VideoInfo> GetVideosGroupedByVersion(List <VideoInfo> videos) { if (videos.Count == 0) { return(videos); } var list = new List <VideoInfo>(); var folderName = Path.GetFileName(Path.GetDirectoryName(videos[0].Files[0].Path)); if (!string.IsNullOrEmpty(folderName) && folderName.Length > 1 && videos.All(i => i.Files.Count == 1 && IsEligibleForMultiVersion(folderName, i.Files[0].Path)) && HaveSameYear(videos)) { var ordered = videos.OrderBy(i => i.Name).ToList(); list.Add(ordered[0]); var alternateVersionsLen = ordered.Count - 1; var alternateVersions = new VideoFileInfo[alternateVersionsLen]; for (int i = 0; i < alternateVersionsLen; i++) { alternateVersions[i] = ordered[i + 1].Files[0]; } list[0].AlternateVersions = alternateVersions; list[0].Name = folderName; var extras = ordered.Skip(1).SelectMany(i => i.Extras).ToList(); extras.AddRange(list[0].Extras); list[0].Extras = extras; return(list); } return(videos); }
/// <summary> /// Finds extras matching the video info. /// </summary> /// <param name="files">The list of file video infos.</param> /// <param name="videoInfo">The video to compare against.</param> /// <param name="videoFlagDelimiters">The video flag delimiters.</param> /// <returns>A list of video extras for [videoInfo].</returns> public static IReadOnlyList <VideoFileInfo> GetExtras(IReadOnlyList <VideoInfo> files, VideoFileInfo videoInfo, ReadOnlySpan <char> videoFlagDelimiters) { var parentDir = videoInfo.IsDirectory ? videoInfo.Path : Path.GetDirectoryName(videoInfo.Path.AsSpan()); var trimmedFileNameWithoutExtension = TrimFilenameDelimiters(videoInfo.FileNameWithoutExtension, videoFlagDelimiters); var trimmedVideoInfoName = TrimFilenameDelimiters(videoInfo.Name, videoFlagDelimiters); var result = new List <VideoFileInfo>(); for (var pos = files.Count - 1; pos >= 0; pos--) { var current = files[pos]; // ignore non-extras and multi-file (can this happen?) if (current.ExtraType == null || current.Files.Count > 1) { continue; } var currentFile = current.Files[0]; var trimmedCurrentFileName = TrimFilenameDelimiters(currentFile.Name, videoFlagDelimiters); // first check filenames bool isValid = StartsWith(trimmedCurrentFileName, trimmedFileNameWithoutExtension) || (StartsWith(trimmedCurrentFileName, trimmedVideoInfoName) && currentFile.Year == videoInfo.Year); // then by directory if (!isValid) { // When the extra rule type is DirectoryName we must go one level higher to get the "real" dir name var currentParentDir = currentFile.ExtraRule?.RuleType == ExtraRuleType.DirectoryName ? Path.GetDirectoryName(Path.GetDirectoryName(currentFile.Path.AsSpan())) : Path.GetDirectoryName(currentFile.Path.AsSpan()); isValid = !currentParentDir.IsEmpty && !parentDir.IsEmpty && currentParentDir.Equals(parentDir, StringComparison.OrdinalIgnoreCase); } if (isValid) { result.Add(currentFile); } } return(result.OrderBy(r => r.Path).ToArray()); }