diff --git a/SabreTools.DatFiles/DatFile.cs b/SabreTools.DatFiles/DatFile.cs index 6c0e781f..44530a0c 100644 --- a/SabreTools.DatFiles/DatFile.cs +++ b/SabreTools.DatFiles/DatFile.cs @@ -782,6 +782,197 @@ namespace SabreTools.DatFiles return false; } + /// + /// Resolve name duplicates in an arbitrary set of DatItems based on the supplied information + /// + /// List of DatItem objects representing the items to be merged + /// A List of DatItem objects representing the renamed items + protected List ResolveNames(List items) + { + // Create the output list + List output = []; + + // First we want to make sure the list is in alphabetical order + DatItemTool.Sort(ref items, true); + + // Now we want to loop through and check names + DatItem? lastItem = null; + string? lastrenamed = null; + int lastid = 0; + for (int i = 0; i < items.Count; i++) + { + DatItem datItem = items[i]; + + // If we have the first item, we automatically add it + if (lastItem == null) + { + output.Add(datItem); + lastItem = datItem; + continue; + } + + // Get the last item name, if applicable + string lastItemName = lastItem.GetName() + ?? lastItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() + ?? string.Empty; + + // Get the current item name, if applicable + string datItemName = datItem.GetName() + ?? datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() + ?? string.Empty; + + // If the current item exactly matches the last item, then we don't add it +#if NET20 || NET35 + if ((datItem.GetDuplicateStatus(lastItem) & DupeType.All) != 0) +#else + if (datItem.GetDuplicateStatus(lastItem).HasFlag(DupeType.All)) +#endif + { + logger.Verbose($"Exact duplicate found for '{datItemName}'"); + continue; + } + + // If the current name matches the previous name, rename the current item + else if (datItemName == lastItemName) + { + logger.Verbose($"Name duplicate found for '{datItemName}'"); + + if (datItem is Disk || datItem is DatItems.Formats.File || datItem is Media || datItem is Rom) + { + datItemName += GetDuplicateSuffix(datItem); + lastrenamed ??= datItemName; + } + + // If we have a conflict with the last renamed item, do the right thing + if (datItemName == lastrenamed) + { + lastrenamed = datItemName; + datItemName += (lastid == 0 ? string.Empty : "_" + lastid); + lastid++; + } + // If we have no conflict, then we want to reset the lastrenamed and id + else + { + lastrenamed = null; + lastid = 0; + } + + // Set the item name back to the datItem + datItem.SetName(datItemName); + + output.Add(datItem); + } + + // Otherwise, we say that we have a valid named file + else + { + output.Add(datItem); + lastItem = datItem; + lastrenamed = null; + lastid = 0; + } + } + + // One last sort to make sure this is ordered + DatItemTool.Sort(ref output, true); + + return output; + } + + /// + /// Resolve name duplicates in an arbitrary set of DatItems based on the supplied information + /// + /// List of item ID to DatItem mappings representing the items to be merged + /// A List of DatItem objects representing the renamed items + protected List> ResolveNamesDB(List> mappings) + { + // Create the output dict + List> output = []; + + // First we want to make sure the list is in alphabetical order + DatItemTool.SortDB(ref mappings, true); + + // Now we want to loop through and check names + DatItem? lastItem = null; + string? lastrenamed = null; + int lastid = 0; + foreach (var datItem in mappings) + { + // If we have the first item, we automatically add it + if (lastItem == null) + { + output.Add(datItem); + lastItem = datItem.Value; + continue; + } + + // Get the last item name, if applicable + string lastItemName = lastItem.GetName() + ?? lastItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() + ?? string.Empty; + + // Get the current item name, if applicable + string datItemName = datItem.Value.GetName() + ?? datItem.Value.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() + ?? string.Empty; + + // If the current item exactly matches the last item, then we don't add it +#if NET20 || NET35 + if ((datItem.Value.GetDuplicateStatus(lastItem) & DupeType.All) != 0) +#else + if (datItem.Value.GetDuplicateStatus(lastItem).HasFlag(DupeType.All)) +#endif + { + logger.Verbose($"Exact duplicate found for '{datItemName}'"); + continue; + } + + // If the current name matches the previous name, rename the current item + else if (datItemName == lastItemName) + { + logger.Verbose($"Name duplicate found for '{datItemName}'"); + + if (datItem.Value is Disk || datItem.Value is DatItems.Formats.File || datItem.Value is Media || datItem.Value is Rom) + { + datItemName += GetDuplicateSuffix(datItem.Value); + lastrenamed ??= datItemName; + } + + // If we have a conflict with the last renamed item, do the right thing + if (datItemName == lastrenamed) + { + lastrenamed = datItemName; + datItemName += (lastid == 0 ? string.Empty : "_" + lastid); + lastid++; + } + // If we have no conflict, then we want to reset the lastrenamed and id + else + { + lastrenamed = null; + lastid = 0; + } + + // Set the item name back to the datItem + datItem.Value.SetName(datItemName); + output.Add(datItem); + } + + // Otherwise, we say that we have a valid named file + else + { + output.Add(datItem); + lastItem = datItem.Value; + lastrenamed = null; + lastid = 0; + } + } + + // One last sort to make sure this is ordered + DatItemTool.SortDB(ref output, true); + + return output; + } + /// /// Get if an item should be ignored on write /// @@ -852,6 +1043,21 @@ namespace SabreTools.DatFiles return false; } + /// + /// Get duplicate suffix based on the item type + /// + private static string GetDuplicateSuffix(DatItem datItem) + { + return datItem switch + { + Disk disk => disk.GetDuplicateSuffix(), + DatItems.Formats.File file => file.GetDuplicateSuffix(), + Media media => media.GetDuplicateSuffix(), + Rom rom => rom.GetDuplicateSuffix(), + _ => "_1", + }; + } + #endregion } } diff --git a/SabreTools.DatFiles/Formats/Missfile.cs b/SabreTools.DatFiles/Formats/Missfile.cs index 28608c58..0d2dd074 100644 --- a/SabreTools.DatFiles/Formats/Missfile.cs +++ b/SabreTools.DatFiles/Formats/Missfile.cs @@ -64,7 +64,7 @@ namespace SabreTools.DatFiles.Formats continue; // Resolve the names in the block - datItems = DatItemTool.ResolveNames(datItems); + datItems = ResolveNames(datItems); for (int index = 0; index < datItems.Count; index++) { @@ -124,7 +124,7 @@ namespace SabreTools.DatFiles.Formats continue; // Resolve the names in the block - var items = DatItemTool.ResolveNamesDB([.. itemsDict]); + var items = ResolveNamesDB([.. itemsDict]); foreach (var kvp in items) { diff --git a/SabreTools.DatFiles/Formats/SabreJSON.cs b/SabreTools.DatFiles/Formats/SabreJSON.cs index 9288bde1..9f2daf89 100644 --- a/SabreTools.DatFiles/Formats/SabreJSON.cs +++ b/SabreTools.DatFiles/Formats/SabreJSON.cs @@ -399,7 +399,7 @@ namespace SabreTools.DatFiles.Formats continue; // Resolve the names in the block - datItems = DatItemTool.ResolveNames(datItems); + datItems = ResolveNames(datItems); for (int index = 0; index < datItems.Count; index++) { @@ -479,7 +479,7 @@ namespace SabreTools.DatFiles.Formats continue; // Resolve the names in the block - var items = DatItemTool.ResolveNamesDB([.. itemsDict]); + var items = ResolveNamesDB([.. itemsDict]); foreach (var kvp in items) { diff --git a/SabreTools.DatFiles/Formats/SabreXML.cs b/SabreTools.DatFiles/Formats/SabreXML.cs index 63bda68d..828ee3c3 100644 --- a/SabreTools.DatFiles/Formats/SabreXML.cs +++ b/SabreTools.DatFiles/Formats/SabreXML.cs @@ -227,7 +227,7 @@ namespace SabreTools.DatFiles.Formats continue; // Resolve the names in the block - datItems = DatItemTool.ResolveNames(datItems); + datItems = ResolveNames(datItems); for (int index = 0; index < datItems.Count; index++) { @@ -308,7 +308,7 @@ namespace SabreTools.DatFiles.Formats continue; // Resolve the names in the block - var items = DatItemTool.ResolveNamesDB([.. itemsDict]); + var items = ResolveNamesDB([.. itemsDict]); foreach (var kvp in items) { diff --git a/SabreTools.DatItems/DatItemTool.cs b/SabreTools.DatItems/DatItemTool.cs index 22bcef32..69946da6 100644 --- a/SabreTools.DatItems/DatItemTool.cs +++ b/SabreTools.DatItems/DatItemTool.cs @@ -370,212 +370,6 @@ namespace SabreTools.DatItems return output; } - /// - /// Resolve name duplicates in an arbitrary set of DatItems based on the supplied information - /// - /// List of DatItem objects representing the items to be merged - /// A List of DatItem objects representing the renamed items - public static List ResolveNames(List items) - { - // Create the output list - List output = []; - - // First we want to make sure the list is in alphabetical order - Sort(ref items, true); - - // Now we want to loop through and check names - DatItem? lastItem = null; - string? lastrenamed = null; - int lastid = 0; - for (int i = 0; i < items.Count; i++) - { - DatItem datItem = items[i]; - - // If we have the first item, we automatically add it - if (lastItem == null) - { - output.Add(datItem); - lastItem = datItem; - continue; - } - - // Get the last item name, if applicable - string lastItemName = lastItem.GetName() - ?? lastItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() - ?? string.Empty; - - // Get the current item name, if applicable - string datItemName = datItem.GetName() - ?? datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() - ?? string.Empty; - - // If the current item exactly matches the last item, then we don't add it -#if NET20 || NET35 - if ((datItem.GetDuplicateStatus(lastItem) & DupeType.All) != 0) -#else - if (datItem.GetDuplicateStatus(lastItem).HasFlag(DupeType.All)) -#endif - { - staticLogger.Verbose($"Exact duplicate found for '{datItemName}'"); - continue; - } - - // If the current name matches the previous name, rename the current item - else if (datItemName == lastItemName) - { - staticLogger.Verbose($"Name duplicate found for '{datItemName}'"); - - if (datItem is Disk || datItem is Formats.File || datItem is Media || datItem is Rom) - { - datItemName += GetDuplicateSuffix(datItem); - lastrenamed ??= datItemName; - } - - // If we have a conflict with the last renamed item, do the right thing - if (datItemName == lastrenamed) - { - lastrenamed = datItemName; - datItemName += (lastid == 0 ? string.Empty : "_" + lastid); - lastid++; - } - // If we have no conflict, then we want to reset the lastrenamed and id - else - { - lastrenamed = null; - lastid = 0; - } - - // Set the item name back to the datItem - datItem.SetName(datItemName); - - output.Add(datItem); - } - - // Otherwise, we say that we have a valid named file - else - { - output.Add(datItem); - lastItem = datItem; - lastrenamed = null; - lastid = 0; - } - } - - // One last sort to make sure this is ordered - Sort(ref output, true); - - return output; - } - - /// - /// Resolve name duplicates in an arbitrary set of DatItems based on the supplied information - /// - /// List of item ID to DatItem mappings representing the items to be merged - /// A List of DatItem objects representing the renamed items - public static List> ResolveNamesDB(List> mappings) - { - // Create the output dict - List> output = []; - - // First we want to make sure the list is in alphabetical order - SortDB(ref mappings, true); - - // Now we want to loop through and check names - DatItem? lastItem = null; - string? lastrenamed = null; - int lastid = 0; - foreach (var datItem in mappings) - { - // If we have the first item, we automatically add it - if (lastItem == null) - { - output.Add(datItem); - lastItem = datItem.Value; - continue; - } - - // Get the last item name, if applicable - string lastItemName = lastItem.GetName() - ?? lastItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() - ?? string.Empty; - - // Get the current item name, if applicable - string datItemName = datItem.Value.GetName() - ?? datItem.Value.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue() - ?? string.Empty; - - // If the current item exactly matches the last item, then we don't add it -#if NET20 || NET35 - if ((datItem.Value.GetDuplicateStatus(lastItem) & DupeType.All) != 0) -#else - if (datItem.Value.GetDuplicateStatus(lastItem).HasFlag(DupeType.All)) -#endif - { - staticLogger.Verbose($"Exact duplicate found for '{datItemName}'"); - continue; - } - - // If the current name matches the previous name, rename the current item - else if (datItemName == lastItemName) - { - staticLogger.Verbose($"Name duplicate found for '{datItemName}'"); - - if (datItem.Value is Disk || datItem.Value is Formats.File || datItem.Value is Media || datItem.Value is Rom) - { - datItemName += GetDuplicateSuffix(datItem.Value); - lastrenamed ??= datItemName; - } - - // If we have a conflict with the last renamed item, do the right thing - if (datItemName == lastrenamed) - { - lastrenamed = datItemName; - datItemName += (lastid == 0 ? string.Empty : "_" + lastid); - lastid++; - } - // If we have no conflict, then we want to reset the lastrenamed and id - else - { - lastrenamed = null; - lastid = 0; - } - - // Set the item name back to the datItem - datItem.Value.SetName(datItemName); - output.Add(datItem); - } - - // Otherwise, we say that we have a valid named file - else - { - output.Add(datItem); - lastItem = datItem.Value; - lastrenamed = null; - lastid = 0; - } - } - - // One last sort to make sure this is ordered - SortDB(ref output, true); - - return output; - } - - /// - /// Get duplicate suffix based on the item type - /// - private static string GetDuplicateSuffix(DatItem datItem) - { - return datItem switch - { - Disk disk => disk.GetDuplicateSuffix(), - Formats.File file => file.GetDuplicateSuffix(), - Media media => media.GetDuplicateSuffix(), - Rom rom => rom.GetDuplicateSuffix(), - _ => "_1", - }; - } - /// /// Sort a list of DatItem objects by SourceID, Game, and Name (in order) ///