From fdb14f5b6af9627ab2efb8d1bbba65362b38bd7a Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 5 Dec 2016 11:43:48 -0800 Subject: [PATCH] [DatFile, Flags] Allow for muliple stat output formats at once --- SabreTools.Helper/Data/Enums.cs | 11 - SabreTools.Helper/Data/Flags.cs | 12 + .../Dats/Partials/DatFile.Statistics.cs | 403 ++++++++++-------- SabreTools/SabreTools.cs | 8 +- 4 files changed, 234 insertions(+), 200 deletions(-) diff --git a/SabreTools.Helper/Data/Enums.cs b/SabreTools.Helper/Data/Enums.cs index d2ac89b6..8278ebdb 100644 --- a/SabreTools.Helper/Data/Enums.cs +++ b/SabreTools.Helper/Data/Enums.cs @@ -285,17 +285,6 @@ NotNodump = 5, // This is a fake flag that is used for filter only } - /// - /// Determine which format to output Stats to - /// - public enum StatDatFormat - { - None = 0, - HTML = 1, - CSV = 2, - TSV = 3, - } - #endregion #region Skippers and Mappers diff --git a/SabreTools.Helper/Data/Flags.cs b/SabreTools.Helper/Data/Flags.cs index d9f1f2c8..b08868d5 100644 --- a/SabreTools.Helper/Data/Flags.cs +++ b/SabreTools.Helper/Data/Flags.cs @@ -227,6 +227,18 @@ namespace SabreTools.Helper.Data ALL = 0xFFFF, } + /// + /// Determine which format to output Stats to + /// + /// [Flags] + public enum StatDatFormat + { + None = 0x01, + HTML = 0x02, + CSV = 0x04, + TSV = 0x08, + } + #endregion #region DatItem related diff --git a/SabreTools.Helper/Dats/Partials/DatFile.Statistics.cs b/SabreTools.Helper/Dats/Partials/DatFile.Statistics.cs index cfe953b7..ac981190 100644 --- a/SabreTools.Helper/Dats/Partials/DatFile.Statistics.cs +++ b/SabreTools.Helper/Dats/Partials/DatFile.Statistics.cs @@ -77,14 +77,15 @@ namespace SabreTools.Helper.Dats /// /// Output the stats for the Dat in a human-readable format /// - /// StreamWriter representing the output file or stream for the statistics + /// Dictionary representing the outputs /// Set the statistics output format to use /// Logger object for file and console writing /// True if numbers should be recalculated for the DAT, false otherwise (default) /// Number of games to use, -1 means recalculate games (default) /// True if baddumps should be included in output, false otherwise (default) /// True if nodumps should be included in output, false otherwise (default) - public void OutputStats(StreamWriter sw, StatDatFormat statDatFormat, Logger logger, bool recalculate = false, long game = -1, bool baddumpCol = false, bool nodumpCol = false) + public void OutputStats(Dictionary outputs, StatDatFormat statDatFormat, Logger logger, bool recalculate = false, + long game = -1, bool baddumpCol = false, bool nodumpCol = false) { // If we're supposed to recalculate the statistics, do so if (recalculate) @@ -122,10 +123,31 @@ namespace SabreTools.Helper.Dats // Now write it out to file as well string line = ""; - switch (statDatFormat) + if (outputs.ContainsKey(StatDatFormat.None)) { - case StatDatFormat.CSV: - line = "\"" + FileName + "\"," + line = @"'" + FileName + @"': +-------------------------------------------------- + Uncompressed size: " + Style.GetBytesReadable(TotalSize) + @" + Games found: " + (game == -1 ? Count : game) + @" + Roms found: " + RomCount + @" + Disks found: " + DiskCount + @" + Roms with CRC: " + CRCCount + @" + Roms with MD5: " + MD5Count + @" + Roms with SHA-1: " + SHA1Count + "\n"; + + if (baddumpCol) + { + line += " Roms with BadDump status: " + BaddumpCount + "\n"; + } + if (nodumpCol) + { + line += " Roms with Nodump status: " + NodumpCount + "\n"; + } + outputs[StatDatFormat.None].Write(line); + } + if (outputs.ContainsKey(StatDatFormat.CSV)) + { + line = "\"" + FileName + "\"," + "\"" + TotalSize + "\"," + "\"" + (game == -1 ? Count : game) + "\"," + "\"" + RomCount + "\"," @@ -134,19 +156,21 @@ namespace SabreTools.Helper.Dats + "\"" + MD5Count + "\"," + "\"" + SHA1Count + "\""; - if (baddumpCol) - { - line += ",\"" + BaddumpCount + "\""; - } - if (nodumpCol) - { - line += ",\"" + NodumpCount + "\""; - } + if (baddumpCol) + { + line += ",\"" + BaddumpCount + "\""; + } + if (nodumpCol) + { + line += ",\"" + NodumpCount + "\""; + } - line += "\n"; - break; - case StatDatFormat.HTML: - line = "\t\t\t" + HttpUtility.HtmlEncode(FileName.Remove(0, 5)) : ">" + HttpUtility.HtmlEncode(FileName)) + "" + "" + Style.GetBytesReadable(TotalSize) + "" @@ -157,40 +181,21 @@ namespace SabreTools.Helper.Dats + "" + MD5Count + "" + "" + SHA1Count + ""; - if (baddumpCol) - { - line += "" + BaddumpCount + ""; - } - if (nodumpCol) - { - line += "" + NodumpCount + ""; - } + if (baddumpCol) + { + line += "" + BaddumpCount + ""; + } + if (nodumpCol) + { + line += "" + NodumpCount + ""; + } - line += "\n"; - break; - case StatDatFormat.None: - default: - line = @"'" + FileName + @"': --------------------------------------------------- - Uncompressed size: " + Style.GetBytesReadable(TotalSize) + @" - Games found: " + (game == -1 ? Count : game) + @" - Roms found: " + RomCount + @" - Disks found: " + DiskCount + @" - Roms with CRC: " + CRCCount + @" - Roms with MD5: " + MD5Count + @" - Roms with SHA-1: " + SHA1Count + "\n"; - - if (baddumpCol) - { - line += " Roms with BadDump status: " + BaddumpCount + "\n"; - } - if (nodumpCol) - { - line += " Roms with Nodump status: " + NodumpCount + "\n"; - } - break; - case StatDatFormat.TSV: - line = "\"" + FileName + "\"\t" + line += "\n"; + outputs[StatDatFormat.HTML].Write(line); + } + if (outputs.ContainsKey(StatDatFormat.TSV)) + { + line = "\"" + FileName + "\"\t" + "\"" + TotalSize + "\"\t" + "\"" + (game == -1 ? Count : game) + "\"\t" + "\"" + RomCount + "\"\t" @@ -199,21 +204,18 @@ namespace SabreTools.Helper.Dats + "\"" + MD5Count + "\"\t" + "\"" + SHA1Count + "\""; - if (baddumpCol) - { - line += "\t\"" + BaddumpCount + "\""; - } - if (nodumpCol) - { - line += "\t\"" + NodumpCount + "\""; - } + if (baddumpCol) + { + line += "\t\"" + BaddumpCount + "\""; + } + if (nodumpCol) + { + line += "\t\"" + NodumpCount + "\""; + } - line += "\n"; - break; + line += "\n"; + outputs[StatDatFormat.TSV].Write(line); } - - // Output the line to the streamwriter - sw.Write(line); } #endregion @@ -237,6 +239,12 @@ namespace SabreTools.Helper.Dats public static void OutputStats(List inputs, string reportName, string outDir, bool single, bool baddumpCol, bool nodumpCol, StatDatFormat statDatFormat, Logger logger) { + // If there's no output format, set the default + if (statDatFormat == 0x0) + { + statDatFormat = StatDatFormat.None; + } + // Get the proper output file name if (String.IsNullOrEmpty(outDir)) { @@ -247,11 +255,9 @@ namespace SabreTools.Helper.Dats reportName = "report"; } outDir = Path.GetFullPath(outDir); - reportName = Style.GetFileNameWithoutExtension(reportName) + OutputStatsGetExtension(statDatFormat); - Path.Combine(outDir, reportName); - // Create the StreamWriter for this file - StreamWriter sw = new StreamWriter(File.Open(reportName, FileMode.Create, FileAccess.Write)); + // Get the dictionary of desired outputs + Dictionary outputs = OutputStatsGetOutputWriters(statDatFormat, reportName, outDir); // Make sure we have all files List> newinputs = new List>(); // item, basepath @@ -275,7 +281,7 @@ namespace SabreTools.Helper.Dats .ToList(); // Write the header, if any - OutputStatsWriteHeader(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteHeader(outputs, statDatFormat, baddumpCol, nodumpCol); // Init all total variables long totalSize = 0; @@ -312,7 +318,7 @@ namespace SabreTools.Helper.Dats if (lastdir != null && thisdir != lastdir) { // Output separator if needed - OutputStatsWriteMidSeparator(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidSeparator(outputs, statDatFormat, baddumpCol, nodumpCol); DatFile lastdirdat = new DatFile { @@ -326,13 +332,13 @@ namespace SabreTools.Helper.Dats BaddumpCount = dirBaddump, NodumpCount = dirNodump, }; - lastdirdat.OutputStats(sw, statDatFormat, logger, game: dirGame, baddumpCol: baddumpCol, nodumpCol: nodumpCol); + lastdirdat.OutputStats(outputs, statDatFormat, logger, game: dirGame, baddumpCol: baddumpCol, nodumpCol: nodumpCol); // Write the mid-footer, if any - OutputStatsWriteMidFooter(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidFooter(outputs, statDatFormat, baddumpCol, nodumpCol); // Write the header, if any - OutputStatsWriteMidHeader(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidHeader(outputs, statDatFormat, baddumpCol, nodumpCol); // Reset the directory stats dirSize = 0; @@ -356,7 +362,7 @@ namespace SabreTools.Helper.Dats logger.User("Adding stats for file '" + filename.Item1 + "'\n", false); if (single) { - datdata.OutputStats(sw, statDatFormat, logger, baddumpCol: baddumpCol, nodumpCol: nodumpCol); + datdata.OutputStats(outputs, statDatFormat, logger, baddumpCol: baddumpCol, nodumpCol: nodumpCol); } // Add single DAT stats to dir @@ -386,7 +392,7 @@ namespace SabreTools.Helper.Dats } // Output the directory stats one last time - OutputStatsWriteMidSeparator(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidSeparator(outputs, statDatFormat, baddumpCol, nodumpCol); if (single) { @@ -402,14 +408,14 @@ namespace SabreTools.Helper.Dats BaddumpCount = dirBaddump, NodumpCount = dirNodump, }; - dirdat.OutputStats(sw, statDatFormat, logger, game: dirGame, baddumpCol: baddumpCol, nodumpCol: nodumpCol); + dirdat.OutputStats(outputs, statDatFormat, logger, game: dirGame, baddumpCol: baddumpCol, nodumpCol: nodumpCol); } // Write the mid-footer, if any - OutputStatsWriteMidFooter(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidFooter(outputs, statDatFormat, baddumpCol, nodumpCol); // Write the header, if any - OutputStatsWriteMidHeader(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidHeader(outputs, statDatFormat, baddumpCol, nodumpCol); // Reset the directory stats dirSize = 0; @@ -434,13 +440,17 @@ namespace SabreTools.Helper.Dats BaddumpCount = totalBaddump, NodumpCount = totalNodump, }; - totaldata.OutputStats(sw, statDatFormat, logger, game: totalGame, baddumpCol: baddumpCol, nodumpCol: nodumpCol); + totaldata.OutputStats(outputs, statDatFormat, logger, game: totalGame, baddumpCol: baddumpCol, nodumpCol: nodumpCol); // Output footer if needed - OutputStatsWriteFooter(sw, statDatFormat); + OutputStatsWriteFooter(outputs, statDatFormat); - sw.Flush(); - sw.Dispose(); + // Flush and dispose of the stream writers + foreach (StatDatFormat format in outputs.Keys) + { + outputs[format].Flush(); + outputs[format].Dispose(); + } logger.User(@" Please check the log folder if the stats scrolled offscreen", false); @@ -450,47 +460,71 @@ Please check the log folder if the stats scrolled offscreen", false); /// Get the proper extension for the stat output format /// /// StatDatFormat to get the extension for - /// File extension with leading period - private static string OutputStatsGetExtension(StatDatFormat statDatFormat) + /// Name of the input file to use + /// Output path to use + /// Dictionary of file types to StreamWriters + private static Dictionary OutputStatsGetOutputWriters(StatDatFormat statDatFormat, string reportName, string outDir) { - string reportExtension = ""; - switch (statDatFormat) + Dictionary output = new Dictionary(); + + // For each output format, get the appropriate stream writer + if ((statDatFormat & StatDatFormat.None) != 0) { - case StatDatFormat.CSV: - reportExtension = ".csv"; - break; - case StatDatFormat.HTML: - reportExtension = ".html"; - break; - case StatDatFormat.None: - default: - reportExtension = ".txt"; - break; - case StatDatFormat.TSV: - reportExtension = ".csv"; - break; + reportName = Style.GetFileNameWithoutExtension(reportName) + ".txt"; + Path.Combine(outDir, reportName); + + // Create the StreamWriter for this file + output.Add(StatDatFormat.None, new StreamWriter(File.Open(reportName, FileMode.Create, FileAccess.Write))); } - return reportExtension; + if ((statDatFormat & StatDatFormat.CSV) != 0) + { + reportName = Style.GetFileNameWithoutExtension(reportName) + ".csv"; + Path.Combine(outDir, reportName); + + // Create the StreamWriter for this file + output.Add(StatDatFormat.CSV, new StreamWriter(File.Open(reportName, FileMode.Create, FileAccess.Write))); + } + if ((statDatFormat & StatDatFormat.HTML) != 0) + { + reportName = Style.GetFileNameWithoutExtension(reportName) + ".html"; + Path.Combine(outDir, reportName); + + // Create the StreamWriter for this file + output.Add(StatDatFormat.HTML, new StreamWriter(File.Open(reportName, FileMode.Create, FileAccess.Write))); + } + if ((statDatFormat & StatDatFormat.TSV) != 0) + { + reportName = Style.GetFileNameWithoutExtension(reportName) + ".csv"; + Path.Combine(outDir, reportName); + + // Create the StreamWriter for this file + output.Add(StatDatFormat.TSV, new StreamWriter(File.Open(reportName, FileMode.Create, FileAccess.Write))); + } + + return output; } /// /// Write out the header to the stream, if any exists /// - /// StreamWriter representing the output + /// Dictionary representing the outputs /// StatDatFormat representing output format /// True if baddumps should be included in output, false otherwise /// True if nodumps should be included in output, false otherwise - private static void OutputStatsWriteHeader(StreamWriter sw, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) + private static void OutputStatsWriteHeader(Dictionary outputs, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) { - string head = ""; - switch (statDatFormat) + if (outputs.ContainsKey(StatDatFormat.None)) { - case StatDatFormat.CSV: - head = "\"File Name\",\"Total Size\",\"Games\",\"Roms\",\"Disks\",\"# with CRC\",\"# with MD5\",\"# with SHA-1\"" - + (baddumpCol ? ",\"BadDumps\"" : "") + (nodumpCol ? ",\"Nodumps\"" : "") + "\n"; - break; - case StatDatFormat.HTML: - head = @" + // Nothing + } + if (outputs.ContainsKey(StatDatFormat.CSV)) + { + outputs[StatDatFormat.CSV].Write("\"File Name\",\"Total Size\",\"Games\",\"Roms\",\"Disks\",\"# with CRC\",\"# with MD5\",\"# with SHA-1\"" + + (baddumpCol ? ",\"BadDumps\"" : "") + (nodumpCol ? ",\"Nodumps\"" : "") + "\n"); + } + if (outputs.ContainsKey(StatDatFormat.HTML)) + { + outputs[StatDatFormat.HTML].Write(@"
DAT Statistics Report @@ -509,115 +543,113 @@ Please check the log folder if the stats scrolled offscreen", false);

DAT Statistics Report (" + DateTime.Now.ToShortDateString() + @")

-"; - break; - case StatDatFormat.None: - default: - break; - case StatDatFormat.TSV: - head = "\"File Name\"\t\"Total Size\"\t\"Games\"\t\"Roms\"\t\"Disks\"\t\"# with CRC\"\t\"# with MD5\"\t\"# with SHA-1\"" - + (baddumpCol ? "\t\"BadDumps\"" : "") + (nodumpCol ? "\t\"Nodumps\"" : "") + "\n"; - break; +"); + } + if (outputs.ContainsKey(StatDatFormat.TSV)) + { + outputs[StatDatFormat.TSV].Write("\"File Name\"\t\"Total Size\"\t\"Games\"\t\"Roms\"\t\"Disks\"\t\"# with CRC\"\t\"# with MD5\"\t\"# with SHA-1\"" + + (baddumpCol ? "\t\"BadDumps\"" : "") + (nodumpCol ? "\t\"Nodumps\"" : "") + "\n"); } - sw.Write(head); // Now write the mid header for those who need it - OutputStatsWriteMidHeader(sw, statDatFormat, baddumpCol, nodumpCol); + OutputStatsWriteMidHeader(outputs, statDatFormat, baddumpCol, nodumpCol); } /// /// Write out the mid-header to the stream, if any exists /// - /// StreamWriter representing the output + /// Dictionary representing the outputs /// StatDatFormat representing output format /// True if baddumps should be included in output, false otherwise /// True if nodumps should be included in output, false otherwise - private static void OutputStatsWriteMidHeader(StreamWriter sw, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) + private static void OutputStatsWriteMidHeader(Dictionary outputs, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) { - string head = ""; - switch (statDatFormat) + if (outputs.ContainsKey(StatDatFormat.None)) { - case StatDatFormat.CSV: - break; - case StatDatFormat.HTML: - head = @" " -+ @"" -+ (baddumpCol ? "" : "") + (nodumpCol ? "" : "") + "\n"; - break; - case StatDatFormat.None: - default: - break; - case StatDatFormat.TSV: - break; + // Nothing + } + if (outputs.ContainsKey(StatDatFormat.CSV)) + { + // Nothing + } + if (outputs.ContainsKey(StatDatFormat.HTML)) + { + outputs[StatDatFormat.HTML].Write(@" " ++ @"" ++ (baddumpCol ? "" : "") + (nodumpCol ? "" : "") + "\n"); + } + if (outputs.ContainsKey(StatDatFormat.TSV)) + { + // Nothing } - sw.Write(head); } /// /// Write out the separator to the stream, if any exists /// - /// StreamWriter representing the output + /// Dictionary representing the outputs /// StatDatFormat representing output format /// True if baddumps should be included in output, false otherwise /// True if nodumps should be included in output, false otherwise - private static void OutputStatsWriteMidSeparator(StreamWriter sw, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) + private static void OutputStatsWriteMidSeparator(Dictionary outputs, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) { - string mid = ""; - switch (statDatFormat) + if (outputs.ContainsKey(StatDatFormat.None)) { - case StatDatFormat.CSV: - break; - case StatDatFormat.HTML: - mid = "\n"; - break; - case StatDatFormat.None: - default: - break; + + "\">\n"); + } + if (outputs.ContainsKey(StatDatFormat.TSV)) + { + // Nothing } - sw.Write(mid); } /// /// Write out the footer-separator to the stream, if any exists /// - /// StreamWriter representing the output + /// Dictionary representing the outputs /// StatDatFormat representing output format /// True if baddumps should be included in output, false otherwise /// True if nodumps should be included in output, false otherwise - private static void OutputStatsWriteMidFooter(StreamWriter sw, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) + private static void OutputStatsWriteMidFooter(Dictionary outputs, StatDatFormat statDatFormat, bool baddumpCol, bool nodumpCol) { - string end = ""; - switch (statDatFormat) + if (outputs.ContainsKey(StatDatFormat.None)) { - case StatDatFormat.CSV: - end = "\n"; - break; - case StatDatFormat.HTML: - end = "\n"; - break; - case StatDatFormat.None: - default: - end = "\n"; - break; - case StatDatFormat.TSV: - end = "\n"; - break; + + "\">\n"); + } + if (outputs.ContainsKey(StatDatFormat.TSV)) + { + outputs[StatDatFormat.TSV].Write("\n"); } - sw.Write(end); } /// @@ -625,26 +657,27 @@ Please check the log folder if the stats scrolled offscreen", false); /// /// StreamWriter representing the output /// StatDatFormat representing output format - private static void OutputStatsWriteFooter(StreamWriter sw, StatDatFormat statDatFormat) + private static void OutputStatsWriteFooter(Dictionary outputs, StatDatFormat statDatFormat) { - string end = ""; - switch (statDatFormat) + if (outputs.ContainsKey(StatDatFormat.None)) { - case StatDatFormat.CSV: - break; - case StatDatFormat.HTML: - end = @"
File NameTotal SizeGamesRomsDisks# with CRC# with MD5# with SHA-1BaddumpsNodumps
File NameTotal SizeGamesRomsDisks# with CRC# with MD5# with SHA-1BaddumpsNodumps
+ // Nothing + } + if (outputs.ContainsKey(StatDatFormat.CSV)) + { + // Nothing + } + if (outputs.ContainsKey(StatDatFormat.HTML)) + { + outputs[StatDatFormat.HTML].Write(@" -"; - break; - case StatDatFormat.None: - default: - break; - case StatDatFormat.TSV: - break; +"); + } + if (outputs.ContainsKey(StatDatFormat.TSV)) + { + // Nothing } - sw.Write(end); } #endregion diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs index c0c05f5c..59f65059 100644 --- a/SabreTools/SabreTools.cs +++ b/SabreTools/SabreTools.cs @@ -101,7 +101,7 @@ namespace SabreTools DatFormat datFormat = 0x0; DiffMode diffMode = 0x0; OutputFormat outputFormat = OutputFormat.Folder; - StatDatFormat statDatFormat = StatDatFormat.None; + StatDatFormat statDatFormat = 0x0; // User inputs int gz = 2, // SimpleSort @@ -242,7 +242,7 @@ namespace SabreTools break; case "-csv": case "--csv": - statDatFormat = StatDatFormat.CSV; + statDatFormat |= StatDatFormat.CSV; break; case "-dd": case "--dedup": @@ -282,7 +282,7 @@ namespace SabreTools break; case "-html": case "--html": - statDatFormat = StatDatFormat.HTML; + statDatFormat |= StatDatFormat.HTML; break; case "-in": case "--inverse": @@ -438,7 +438,7 @@ namespace SabreTools break; case "-tsv": case "--tsv": - statDatFormat = StatDatFormat.TSV; + statDatFormat |= StatDatFormat.TSV; break; case "-txz": case "--txz":