using System; using System.Collections.Generic; using System.Linq; using System.Web; using SabreTools.Helper.Data; namespace SabreTools.Helper.Dats { public partial class DatFile { #region Instance Methods #region Bucketing [MODULAR DONE] /// /// Take the arbitrarily sorted Files Dictionary and convert to one sorted by CRC /// /// True if roms should be deduped, false otherwise /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise public void BucketByCRC(bool mergeroms, Logger logger, bool output = true) { // If we already have the right sorting, trust it if (_sortedBy == SortedBy.CRC) { return; } // Set the sorted type _sortedBy = SortedBy.CRC; SortedDictionary> sortable = new SortedDictionary>(); long count = 0; logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms by CRC"); // Process each all of the roms List keys = Keys.ToList(); foreach (string key in keys) { List roms = this[key]; // If we're merging the roms, do so if (mergeroms) { roms = DatItem.Merge(roms, logger); } // Now add each of the roms to their respective games foreach (DatItem rom in roms) { count++; string newkey = (rom.Type == ItemType.Rom ? ((Rom)rom).CRC : Constants.CRCZero); if (!sortable.ContainsKey(newkey)) { sortable.Add(newkey, new List()); } sortable[newkey].Add(rom); } } // Now go through and sort all of the lists keys = sortable.Keys.ToList(); foreach (string key in keys) { List sortedlist = sortable[key]; DatItem.Sort(ref sortedlist, false); sortable[key] = sortedlist; } // Output the count if told to if (output) { logger.User("A total of " + count + " file hashes will be written out to file"); } // Now assign the dictionary back _files = sortable; } /// /// Take the arbitrarily sorted Files Dictionary and convert to one sorted by Game /// /// True if roms should be deduped, false otherwise /// True if games should only be compared on game and file name, false if system and source are counted /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise /// True if the game should be lowercased (default), false otherwise public void BucketByGame(bool mergeroms, bool norename, Logger logger, bool output = true, bool lower = true) { // If we already have the right sorting, trust it if (_sortedBy == SortedBy.Game) { return; } // Set the sorted type _sortedBy = SortedBy.Game; SortedDictionary> sortable = new SortedDictionary>(); long count = 0; logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms by game"); // Process each all of the roms List keys = Keys.ToList(); foreach (string key in keys) { List roms = this[key]; // If we're merging the roms, do so if (mergeroms) { roms = DatItem.Merge(roms, logger); } // Now add each of the roms to their respective games foreach (DatItem rom in roms) { count++; string newkey = (norename ? "" : rom.SystemID.ToString().PadLeft(10, '0') + "-" + rom.SourceID.ToString().PadLeft(10, '0') + "-") + (String.IsNullOrEmpty(rom.Machine.Name) ? "Default" : rom.Machine.Name); if (lower) { newkey = newkey.ToLowerInvariant(); } newkey = HttpUtility.HtmlEncode(newkey); if (!sortable.ContainsKey(newkey)) { sortable.Add(newkey, new List()); } sortable[newkey].Add(rom); } } // Now go through and sort all of the lists keys = sortable.Keys.ToList(); foreach (string key in keys) { List sortedlist = sortable[key]; DatItem.Sort(ref sortedlist, norename); sortable[key] = sortedlist; } // Output the count if told to if (output) { logger.User("A total of " + count + " file hashes will be written out to file"); } // Now assign the dictionary back _files = sortable; } /// /// Take the arbitrarily sorted Files Dictionary and convert to one sorted by MD5 /// /// True if roms should be deduped, false otherwise /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise public void BucketByMD5(bool mergeroms, Logger logger, bool output = true) { // If we already have the right sorting, trust it if (_sortedBy == SortedBy.MD5) { return; } // Set the sorted type _sortedBy = SortedBy.MD5; SortedDictionary> sortable = new SortedDictionary>(); long count = 0; logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms by MD5"); // Process each all of the roms List keys = Keys.ToList(); foreach (string key in keys) { List roms = this[key]; // If we're merging the roms, do so if (mergeroms) { roms = DatItem.Merge(roms, logger); } // Now add each of the roms to their respective games foreach (DatItem rom in roms) { count++; string newkey = (rom.Type == ItemType.Rom ? ((Rom)rom).MD5 : (rom.Type == ItemType.Disk ? ((Disk)rom).MD5 : Constants.MD5Zero)); if (!sortable.ContainsKey(newkey)) { sortable.Add(newkey, new List()); } sortable[newkey].Add(rom); } } // Now go through and sort all of the lists keys = sortable.Keys.ToList(); foreach (string key in keys) { List sortedlist = sortable[key]; DatItem.Sort(ref sortedlist, false); sortable[key] = sortedlist; } // Output the count if told to if (output) { logger.User("A total of " + count + " file hashes will be written out to file"); } // Now assign the dictionary back _files = sortable; } /// /// Take the arbitrarily sorted Files Dictionary and convert to one sorted by SHA1 /// /// True if roms should be deduped, false otherwise /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise public void BucketBySHA1(bool mergeroms, Logger logger, bool output = true) { // If we already have the right sorting, trust it if (_sortedBy == SortedBy.SHA1) { return; } // Set the sorted type _sortedBy = SortedBy.SHA1; SortedDictionary> sortable = new SortedDictionary>(); long count = 0; logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms by SHA-1"); // Process each all of the roms List keys = Keys.ToList(); foreach (string key in keys) { List roms = this[key]; // If we're merging the roms, do so if (mergeroms) { roms = DatItem.Merge(roms, logger); } // Now add each of the roms to their respective games foreach (DatItem rom in roms) { count++; string newkey = (rom.Type == ItemType.Rom ? ((Rom)rom).SHA1 : (rom.Type == ItemType.Disk ? ((Disk)rom).SHA1 : Constants.MD5Zero)); if (!sortable.ContainsKey(newkey)) { sortable.Add(newkey, new List()); } sortable[newkey].Add(rom); } } // Now go through and sort all of the lists keys = sortable.Keys.ToList(); foreach (string key in keys) { List sortedlist = sortable[key]; DatItem.Sort(ref sortedlist, false); sortable[key] = sortedlist; } // Output the count if told to if (output) { logger.User("A total of " + count + " file hashes will be written out to file"); } // Now assign the dictionary back _files = sortable; } /// /// Take the arbitrarily sorted Files Dictionary and convert to one sorted by Size /// /// True if roms should be deduped, false otherwise /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise public void BucketBySize(bool mergeroms, Logger logger, bool output = true) { // If we already have the right sorting, trust it if (_sortedBy == SortedBy.Size) { return; } // Set the sorted type _sortedBy = SortedBy.Size; SortedDictionary> sortable = new SortedDictionary>(); long count = 0; logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms by size"); // Process each all of the roms List keys = Keys.ToList(); foreach (string key in keys) { List roms = this[key]; // If we're merging the roms, do so if (mergeroms) { roms = DatItem.Merge(roms, logger); } // Now add each of the roms to their respective games foreach (DatItem rom in roms) { count++; string newkey = (rom.Type == ItemType.Rom ? ((Rom)rom).Size.ToString() : "-1"); if (!sortable.ContainsKey(newkey)) { sortable.Add(newkey, new List()); } sortable[newkey].Add(rom); } } // Now go through and sort all of the lists keys = sortable.Keys.ToList(); foreach (string key in keys) { List sortedlist = sortable[key]; DatItem.Sort(ref sortedlist, false); sortable[key] = sortedlist; } // Output the count if told to if (output) { logger.User("A total of " + count + " file hashes will be written out to file"); } // Now assign the dictionary back _files = sortable; } /// /// Use cloneof tags to create merged sets and remove the tags /// /// True if roms should be deduped, false otherwise /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise public void CreateMergedSets(bool mergeroms, Logger logger, bool output = true) { // For sake of ease, the first thing we want to do is sort by game BucketByGame(mergeroms, false, logger, output); // Now we want to loop through all of the games and set the correct information List games = Keys.ToList(); foreach (string game in games) { // Determine if the game has a parent or not string parent = null; if (this[game][0].Machine.CloneOf != null) { parent = this[game][0].Machine.CloneOf; } else if (this[game][0].Machine.RomOf != null) { parent = this[game][0].Machine.RomOf; } // If there is no parent, then we continue if (parent == null) { continue; } // If the parent doesn't exist, then we continue if (this[parent].Count == 0) { continue; } // Otherwise, move the items from the current game to a subfolder of the parent game Machine parentMachine = this[parent][0].Machine; List items = this[game]; foreach (DatItem item in items) { item.Name = item.Machine.Name + "\\" + item.Name; item.Machine = parentMachine; } // Finally, remove the old game so it's not picked up by the writer Remove(game); } } /// /// Use cloneof tags to create split sets and remove the tags /// /// True if roms should be deduped, false otherwise /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise public void CreateSplitSets(bool mergeroms, Logger logger, bool output = true) { // For sake of ease, the first thing we want to do is sort by game BucketByGame(mergeroms, false, logger, output); // Now we want to loop through all of the games and set the correct information List games = Keys.ToList(); foreach (string game in games) { // Determine if the game has a parent or not string parent = null; if (this[game][0].Machine.CloneOf != null) { parent = this[game][0].Machine.CloneOf; } else if (this[game][0].Machine.RomOf != null) { parent = this[game][0].Machine.RomOf; } // If there is no parent, then we continue if (parent == null) { continue; } // If the parent doesn't exist, then we continue if (this[parent].Count == 0) { continue; } /* * Okay, so here actual copies of the roms need to be copied into the current game, so * you need to make sure that you make a copy and don't ruin the original version since the original * parnt is still a valid piece of set */ // Otherwise, copy the items from the parent to the current game Machine parentMachine = this[game][0].Machine; List items = this[parent]; foreach (DatItem item in items) { } } } #endregion #endregion // Instance Methods #region Static Methods #region Bucketing [MODULAR DONE] /// /// Take an arbitrarily ordered List and return a Dictionary sorted by Game /// /// Input unsorted list /// True if roms should be deduped, false otherwise /// True if games should only be compared on game and file name, false if system and source are counted /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise /// SortedDictionary bucketed by game name public static SortedDictionary> BucketListByGame(List list, bool mergeroms, bool norename, Logger logger, bool output = true) { logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms for output"); SortedDictionary> sortable = new SortedDictionary>(); long count = 0; // If we have a null dict or an empty one, output a new dictionary if (list == null || list.Count == 0) { return sortable; } // If we're merging the roms, do so if (mergeroms) { list = DatItem.Merge(list, logger); } // Now add each of the roms to their respective games foreach (DatItem rom in list) { if (rom == null) { continue; } count++; string newkey = (norename ? "" : rom.SystemID.ToString().PadLeft(10, '0') + "-" + rom.SourceID.ToString().PadLeft(10, '0') + "-") + (rom.Machine == null || String.IsNullOrEmpty(rom.Machine.Name) ? "Default" : rom.Machine.Name.ToLowerInvariant()); newkey = HttpUtility.HtmlEncode(newkey); if (!sortable.ContainsKey(newkey)) { sortable.Add(newkey, new List()); } sortable[newkey].Add(rom); } return sortable; } #endregion #endregion // Static Methods } }