using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; namespace AutoGroupGenerator { /// /// Helpers for deriving common names and asset types. /// public static class NamingUtil { #region Constants private static readonly Dictionary ExtensionToType = new(StringComparer.OrdinalIgnoreCase) { { ".png", "Texture" }, { ".jpg", "Texture" }, { ".jpeg", "Texture" }, { ".tga", "Texture" }, { ".psd", "Texture" }, { ".psb", "Texture" }, { ".mp3", "Audio" }, { ".wav", "Audio" }, { ".ogg", "Audio" }, { ".prefab", "Prefab" }, { ".fbx", "Model" }, { ".obj", "Model" }, { ".anim", "Animation" }, { ".controller", "Animator" }, { ".mat", "Material" }, { ".shader", "Shader" }, { ".asset", "Asset" } }; #endregion #region Static Methods /// /// Determines whether most items satisfy a predicate. /// /// Items to evaluate. /// Predicate used for matching. /// Minimum ratio of matches required. /// True when the ratio of matches meets or exceeds the threshold. public static bool MostMatch(IEnumerable paths, Func predicate, float minRatio = 0.75f) { if (paths == null) { throw new ArgumentNullException(nameof(paths)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (minRatio < 0f || minRatio > 1f) { throw new ArgumentOutOfRangeException(nameof(minRatio), "minRatio must be between 0 and 1."); } int total = 0, matchCount = 0; foreach (var path in paths) { total++; if (predicate(path)) { matchCount++; } } return total > 0 && matchCount >= total * minRatio; } /// /// Returns the most common element if it meets the ratio threshold. /// /// Items to analyze. /// Minimum ratio of occurrences required. /// The most common element or null if the threshold is not met. public static string GetMajorityElement(IEnumerable items, float minRatio = 0.75f) { if (items == null) { throw new ArgumentNullException(nameof(items)); } if (minRatio < 0f || minRatio > 1f) { throw new ArgumentOutOfRangeException(nameof(minRatio), "minRatio must be between 0 and 1."); } var counts = new Dictionary(); int total = 0; foreach (var item in items) { if (item == null) { continue; } total++; if (!counts.TryAdd(item, 1)) { counts[item]++; } } if (total == 0) { return null; } var (mostCommon, maxCount) = counts.OrderByDescending(kv => kv.Value).First(); return maxCount >= total * minRatio ? mostCommon : null; } /// /// Returns the most common asset type based on file extensions. /// /// File paths to inspect. /// Minimum ratio of occurrences required. /// The most common asset type or null if the threshold is not met. public static string GetMajorityAssetType(IEnumerable filePaths, float minRatio = 0.75f) { if (filePaths == null) { throw new ArgumentNullException(nameof(filePaths)); } var types = filePaths .Select(Path.GetExtension) .Where(ext => !string.IsNullOrEmpty(ext)) .Select(ext => ExtensionToType.TryGetValue(ext, out var type) ? type : "Unknown") .ToList(); return GetMajorityElement(types, minRatio); } /// /// Finds the most common word across a set of names. /// /// Names to analyze. /// Minimum ratio of occurrences required. /// The most common word or null if the threshold is not met. public static string FindMostCommonWord(IEnumerable names, float minRatio = 0.75f) { if (names == null) { throw new ArgumentNullException(nameof(names)); } if (minRatio < 0f || minRatio > 1f) { throw new ArgumentOutOfRangeException(nameof(minRatio), "minRatio must be between 0 and 1."); } var tokenCounts = new Dictionary(StringComparer.OrdinalIgnoreCase); int totalEntries = 0; foreach (var name in names) { if (string.IsNullOrWhiteSpace(name)) { continue; } totalEntries++; var tokens = ExtractTokens(name); foreach (var token in tokens) { if (!tokenCounts.TryAdd(token, 1)) { tokenCounts[token]++; } } } if (totalEntries == 0 || tokenCounts.Count == 0) { return null; } var (mostCommon, count) = tokenCounts.OrderByDescending(kv => kv.Value).First(); return count >= totalEntries * minRatio ? mostCommon : null; } private static IEnumerable ExtractTokens(string input) { IEnumerable parts = Regex.Matches(input, @"[A-Z]?[a-z]+|[A-Z]+(?![a-z])") .Cast() .Select(m => m.Value); var basicSplit = Regex.Split(input, @"[\s_\-\.0-9]+"); return parts.Concat(basicSplit) .Where(t => !string.IsNullOrWhiteSpace(t)) .Distinct(StringComparer.OrdinalIgnoreCase); } #endregion } }