// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Data; namespace Spludlow.Mame { public class MameReports { public static void Summary() { string[] names = new string[] { "Machine Rom", "Machine Disk", "Software Rom", "Software Disk", }; MameHashStores mameHashStores = new MameHashStores(); HashStore[] hashStores = new HashStore[] { mameHashStores.MachineRom, mameHashStores.MachineDisk, mameHashStores.SoftwareRom, mameHashStores.SoftwareDisk, }; MameDatabaseHashes mameDatabaseHashes = new MameDatabaseHashes(); HashSet[] databaseHashes = new HashSet[] { mameDatabaseHashes.MachineRom, mameDatabaseHashes.MachineDisk, mameDatabaseHashes.SoftwareRom, mameDatabaseHashes.SoftwareDisk, }; // Add unwanted DataTable table = Spludlow.Data.TextTable.ReadText(new string[] { "Store Total Have Missing Unused Complete", "String Int32 Int32 Int32 Int32 String", }); for (int index = 0; index < names.Length; ++index) { string name = names[index]; HashSet databaseHash = databaseHashes[index]; HashStore hashStore = hashStores[index]; string[] missingHashes = MissingHashes(hashStore, databaseHash); string[] unusedHashes = UnusedHashes(hashStore, databaseHash); decimal complete = Math.Round((100.0M / databaseHash.Count) * (databaseHash.Count - missingHashes.Length), 3); table.Rows.Add(name, databaseHash.Count, hashStore.Length, missingHashes.Length, unusedHashes.Length, complete.ToString() + " %"); } MameReport.Report("MAME Complete Summary", table); } public static void MissingMachineRom() { MameHashStores mameHashStores = new MameHashStores(); HashStore hashStore = mameHashStores.MachineRom; HashSet hashSet = MameDatabase.MachineRomHashes(); DataTable table = MameDatabase.MachineRomQuery("sha1 IS NOT NULL"); Missing("Missing Machine Rom", hashStore, hashSet, table); } public static void MissingMachineDisk() { MameHashStores mameHashStores = new MameHashStores(); HashStore hashStore = mameHashStores.MachineDisk; HashSet hashSet = MameDatabase.MachineDiskHashes(); DataTable table = MameDatabase.MachineDiskQuery("sha1 IS NOT NULL"); Missing("Missing Machine Disk", hashStore, hashSet, table); } public static void MissingSoftwareRom() { MameHashStores mameHashStores = new MameHashStores(); HashStore hashStore = mameHashStores.SoftwareRom; HashSet hashSet = MameDatabase.SoftwareRomHashes(); DataTable table = MameDatabase.SoftwareRomQuery("sha1 IS NOT NULL"); Missing("Missing Software Rom", hashStore, hashSet, table); } public static void MissingSoftwareDisk() { MameHashStores mameHashStores = new MameHashStores(); HashStore hashStore = mameHashStores.SoftwareDisk; HashSet hashSet = MameDatabase.SoftwareDiskHashes(); DataTable table = MameDatabase.SoftwareDiskQuery("sha1 IS NOT NULL"); Missing("Missing Software Disk", hashStore, hashSet, table); } public static void Missing(string name, HashStore hashStore, HashSet hashSet, DataTable table) { string[] hashes = MissingHashes(hashStore, hashSet); hashSet = new HashSet(hashes); DataTable missingResultTable = table.Clone(); //int total = 0; foreach (DataRow row in table.Rows) { string sha1 = ((string)row["sha1"]).ToUpper(); //++total; if (hashSet.Contains(sha1) == true) missingResultTable.ImportRow(row); } MameReport.Report(name + ", missing rows " + missingResultTable.Rows.Count + " of " + table.Rows.Count, missingResultTable); } public static string[] MissingHashes(HashStore hashStore, HashSet databaseHashes) { HashSet missing = new HashSet(); foreach (string sha1 in databaseHashes) { if (hashStore.Exists(sha1) == false) missing.Add(sha1); } return missing.ToArray(); } public static string[] UnusedHashes(HashStore hashStore, HashSet databaseHashes) { List notUsed = new List(); foreach (string sha1 in hashStore.Hashes()) { if (databaseHashes.Contains(sha1) == false) notUsed.Add(sha1); } return notUsed.ToArray(); } // // Software Disk by List Count, Size, Projected // public static void SoftwareDiskByList() { MameHashStores stores = new MameHashStores(); HashStore store = stores.SoftwareDisk; DataTable table = MameDatabase.SoftwareDiskQuery("disk.sha1 IS NOT NULL"); DataTable resultTable = Spludlow.Data.TextTable.ReadText(new string[] { "SoftwareList DiskCount DiskHave DiskNeed DiskDup HaveBytes HaveSize Complete ProjectedBytes ProjectedSize Machines", "String Int32 Int32 Int32 Int32 Int64 String Decimal Int64 String String", }); Dictionary> machinesLookup = MameDatabase.GetSoftwareListToMachineLookup(); foreach (string softwareListName in MameDatabase.ExtractSoftwareListNames(table)) { DataRow[] rows = table.Select("softwarelist_name = '" + softwareListName + "'"); HashSet databaseHashes = MameDatabase.ExtractHashset(rows); int totalCount = databaseHashes.Count; int foundCount = 0; int missingCount = 0; int dupCount = rows.Length - databaseHashes.Count; long foundBytes = 0; foreach (string hash in databaseHashes) { if (store.Exists(hash) == true) { foundBytes += Spludlow.Io.Files.FileLength(store.Filename(hash)); ++foundCount; } else { ++missingCount; } } decimal complete = (decimal)foundCount / (decimal)totalCount; long projectedBytes = 0; if (foundBytes > 0) projectedBytes = (long)(((decimal)foundBytes / (decimal)foundCount) * (decimal)totalCount); string machines = null; if (machinesLookup.ContainsKey(softwareListName) == true) machines = ListToCommaText(machinesLookup[softwareListName]); resultTable.Rows.Add(softwareListName, totalCount, foundCount, missingCount, dupCount, foundBytes, Spludlow.Text.DataSize(foundBytes), Math.Round(complete * 100, 0), projectedBytes, Spludlow.Text.DataSize(projectedBytes), machines); } long totalFoundBytes = 0; long totalProjectedBytes = 0; foreach (DataRow row in resultTable.Rows) { totalFoundBytes += (long)row["HaveBytes"]; totalProjectedBytes += (long)row["ProjectedBytes"]; } resultTable.Rows.Add(null, null, null, null, null, totalFoundBytes, Spludlow.Text.DataSize(totalFoundBytes), null, totalProjectedBytes, Spludlow.Text.DataSize(totalProjectedBytes), null); MameReport.Report("Software Disk by List", resultTable); } public static string[] RowsToToCommaTexts(DataRow[] rows, string[] columnNames) { List[] lists = new List[columnNames.Length]; for (int index = 0; index < columnNames.Length; ++index) lists[index] = new List(); foreach (DataRow row in rows) { for (int index = 0; index < columnNames.Length; ++index) { string columnName = columnNames[index]; if (row.IsNull(columnName) == true) continue; string value = (string)row[columnName]; if (lists[index].Contains(value) == false) lists[index].Add(value); } } string[] results = new string[columnNames.Length]; for (int index = 0; index < columnNames.Length; ++index) { lists[index].Sort(); results[index] = ListToCommaText(lists[index]); } return results; } public static string ListToCommaText(List list) { StringBuilder text = new StringBuilder(); foreach (string item in list) { if (text.Length > 0) text.Append(", "); text.Append(item); } return text.ToString(); } public static DataTable LinesToTable(string columnName, string[] lines) { DataTable table = new DataTable(); table.Columns.Add(columnName, typeof(string)); foreach (string line in lines) table.Rows.Add(line); return table; } // // chdman report // public static string ChdInfoMachine() { MameHashStores mameHashStores = new MameHashStores(); HashStore hashStore = mameHashStores.MachineDisk; DataTable databaseTable = MameDatabase.MachineDiskQuery("sha1 IS NOT NULL"); string[] filenames = hashStore.FileNames(); DataTable table = ChdInfo(filenames, -40); DataTable resultTable = new DataTable(); resultTable.Columns.Add("machine_name", typeof(string)); resultTable.Columns.Add("disk_name", typeof(string)); foreach (DataColumn column in table.Columns) resultTable.Columns.Add(column.ColumnName, column.DataType); foreach (DataRow row in table.Rows) { string sha1 = (string)row["Input file"]; DataRow[] databaseRows = databaseTable.Select("sha1 = '" + sha1 + "'"); string[] names = RowsToToCommaTexts(databaseRows, new string[] { "machine_name", "disk_name" }); resultTable.ImportRow(row); DataRow resultRow = resultTable.Rows[resultTable.Rows.Count - 1]; resultRow["machine_name"] = names[0]; resultRow["disk_name"] = names[1]; } MameReport.Report("CHD Info Machine Disk", resultTable); return "CHD Info Machine Disk " + resultTable.Rows.Count; } public static string ChdInfoSoftware() { MameHashStores mameHashStores = new MameHashStores(); HashStore hashStore = mameHashStores.SoftwareDisk; DataTable databaseTable = MameDatabase.SoftwareDiskQuery("sha1 IS NOT NULL"); string[] filenames = hashStore.FileNames(); DataTable table = ChdInfo(filenames, -40); DataTable resultTable = new DataTable(); resultTable.Columns.Add("softwarelist_name", typeof(string)); resultTable.Columns.Add("software_name", typeof(string)); resultTable.Columns.Add("disk_name", typeof(string)); foreach (DataColumn column in table.Columns) resultTable.Columns.Add(column.ColumnName, column.DataType); foreach (DataRow row in table.Rows) { string sha1 = (string)row["Input file"]; DataRow[] databaseRows = databaseTable.Select("sha1 = '" + sha1 + "'"); string[] names = RowsToToCommaTexts(databaseRows, new string[] { "softwarelist_name", "software_name", "disk_name" }); resultTable.ImportRow(row); DataRow resultRow = resultTable.Rows[resultTable.Rows.Count - 1]; resultRow["softwarelist_name"] = names[0]; resultRow["software_name"] = names[1]; resultRow["disk_name"] = names[2]; } MameReport.Report("CHD Info Software Disk", resultTable); return "CHD Info Software Disk " + resultTable.Rows.Count; } public static string ChdInfo(string directory) { string[] filenames = Directory.GetFiles(directory, "*.chd", SearchOption.AllDirectories); DataTable table = ChdInfo(filenames, directory.Length + 1); MameReport.Report("CHD Info Directory", table); return "CHD Info Directory: " + directory + ", " + table.Rows.Count; } public static DataTable ChdInfo(string[] filenames, int nameOffset) { MameChdMan chdMan = new MameChdMan(); DataTable table = new DataTable(); foreach (string filename in filenames) { Dictionary info = chdMan.Info(filename); DataRow row = AddDictToTable(table, info); if (nameOffset != 0) { string name = (string)row["Input file"]; if (nameOffset > 0) row["Input file"] = name.Substring(nameOffset); else row["Input file"] = name.Substring(name.Length + nameOffset); } } table.PrimaryKey = new DataColumn[] { table.Columns["Input file"] }; return table; } public static DataRow AddDictToTable(DataTable table, Dictionary dict) { List columnNames = new List(); foreach (string columnName in dict.Keys) { columnNames.Add(columnName); } foreach (string columnName in columnNames) { if (table.Columns.Contains(columnName) == false) table.Columns.Add(columnName, typeof(string)); } DataRow row = table.NewRow(); foreach (string columnName in columnNames) { row[columnName] = dict[columnName]; } table.Rows.Add(row); return row; } public static string SillyNames() { DataTable[] tables = new DataTable[] { MameDatabase.MachineRomQuery(null), MameDatabase.MachineDiskQuery(null), MameDatabase.SoftwareRomQuery(null), MameDatabase.SoftwareDiskQuery(null), }; string[] tableNames = new string[] { "Machine Rom", "Machine Disk", "Software Rom", "Software Disk", }; string[] fieldNames = new string[] { "machine_name", "softwarelist_name", "software_name", "rom_name", "disk_name", }; DataTable resultTable = Spludlow.Data.TextTable.ReadText(new string[] { "Fails DatabaseTable", "String String", }); foreach (string fieldName in fieldNames) resultTable.Columns.Add(fieldName, typeof(string)); for (int index = 0; index < tables.Length; ++index) { DataTable table = tables[index]; string tableName = tableNames[index]; foreach (DataRow row in table.Rows) { DataRow resultRow = resultTable.NewRow(); resultRow["Fails"] = ""; resultRow["DatabaseTable"] = tableName; List fails = new List(); foreach (string fieldName in fieldNames) { if (table.Columns.IndexOf(fieldName) == -1) continue; if (row.IsNull(fieldName) == true) continue; string name = (string)row[fieldName]; resultRow[fieldName] = name; if (name.Length > 180) fails.Add("Length"); if (Spludlow.Text.IsASCII(name) == false) fails.Add("ASCII"); if (MamePath.IsInvalidFilename(name) == true) fails.Add("Invalid"); } if (fails.Count > 0) { string failText = ""; foreach (string fail in fails) { if (failText.Length > 0) failText += ", "; failText += fail; } resultRow["Fails"] = failText; resultTable.Rows.Add(resultRow); } } } MameReport.Report("Silly Names", resultTable); return "Silly Names " + resultTable.Rows.Count; } } }