/// <summary> /// Write a single set of statistics /// </summary> /// <param name="sw">StreamWriter to write to</param> /// <param name="stat">DatStatistics object to write out</param> /// <param name="baddumpCol">True if baddumps should be included in output, false otherwise</param> /// <param name="nodumpCol">True if nodumps should be included in output, false otherwise</param> private void WriteIndividual(StreamWriter sw, DatStatistics stat, bool baddumpCol, bool nodumpCol) { string line = @"'" + stat.DisplayName + @"': -------------------------------------------------- Uncompressed size: " + GetBytesReadable(stat.Statistics.TotalSize) + @" Games found: " + stat.MachineCount + @" Roms found: " + stat.Statistics.RomCount + @" Disks found: " + stat.Statistics.DiskCount + @" Roms with CRC: " + stat.Statistics.CRCCount + @" Roms with MD5: " + stat.Statistics.MD5Count + @" Roms with SHA-1: " + stat.Statistics.SHA1Count + @" Roms with SHA-256: " + stat.Statistics.SHA256Count + @" Roms with SHA-384: " + stat.Statistics.SHA384Count + @" Roms with SHA-512: " + stat.Statistics.SHA512Count + "\n"; if (baddumpCol) { line += " Roms with BadDump status: "+ stat.Statistics.BaddumpCount + "\n"; } if (nodumpCol) { line += " Roms with Nodump status: "+ stat.Statistics.NodumpCount + "\n"; } // For spacing between DATs line += "\n\n"; sw.Write(line); sw.Flush(); }
/// <inheritdoc/> public override bool WriteToFile(string outfile, bool baddumpCol, bool nodumpCol, bool throwOnError = false) { InternalStopwatch watch = new InternalStopwatch($"Writing statistics to '{outfile}"); try { // Try to create the output file Stream fs = _writeToConsole ? Console.OpenStandardOutput() : File.Create(outfile); if (fs == null) { logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable"); return(false); } StreamWriter sw = new StreamWriter(fs); // Now process each of the statistics for (int i = 0; i < Statistics.Count; i++) { // Get the current statistic DatStatistics stat = Statistics[i]; // If we have a directory statistic if (stat.IsDirectory) { WriteIndividual(sw, stat, baddumpCol, nodumpCol); // If we have anything but the last value, write the separator if (i < Statistics.Count - 1) { WriteFooterSeparator(sw); } } // If we have a normal statistic else { WriteIndividual(sw, stat, baddumpCol, nodumpCol); } } sw.Dispose(); fs.Dispose(); } catch (Exception ex) when(!throwOnError) { logger.Error(ex); return(false); } finally { watch.Stop(); } return(true); }
/// <summary> /// Write a single set of statistics /// </summary> /// <param name="svw">SeparatedValueWriter to write to</param> /// <param name="stat">DatStatistics object to write out</param> /// <param name="baddumpCol">True if baddumps should be included in output, false otherwise</param> /// <param name="nodumpCol">True if nodumps should be included in output, false otherwise</param> private void WriteIndividual(SeparatedValueWriter svw, DatStatistics stat, bool baddumpCol, bool nodumpCol) { string[] values = new string[] { stat.DisplayName, stat.Statistics.TotalSize.ToString(), stat.MachineCount.ToString(), stat.Statistics.RomCount.ToString(), stat.Statistics.DiskCount.ToString(), stat.Statistics.CRCCount.ToString(), stat.Statistics.MD5Count.ToString(), stat.Statistics.SHA1Count.ToString(), stat.Statistics.SHA256Count.ToString(), stat.Statistics.SHA384Count.ToString(), stat.Statistics.SHA512Count.ToString(), baddumpCol ? stat.Statistics.BaddumpCount.ToString() : string.Empty, nodumpCol ? stat.Statistics.NodumpCount.ToString() : string.Empty, }; svw.WriteValues(values); svw.Flush(); }
/// <summary> /// Calculate statistics from a list of inputs /// </summary> /// <param name="inputs">List of input files and folders</param> /// <param name="single">True if single DAT stats are output, false otherwise</param> /// <param name="throwOnError">True if the error that is thrown should be thrown back to the caller, false otherwise</param> public static List <DatStatistics> CalculateStatistics(List <string> inputs, bool single, bool throwOnError = false) { // Create the output list List <DatStatistics> stats = new List <DatStatistics>(); // Make sure we have all files and then order them List <ParentablePath> files = PathTool.GetFilesOnly(inputs); files = files .OrderBy(i => Path.GetDirectoryName(i.CurrentPath)) .ThenBy(i => Path.GetFileName(i.CurrentPath)) .ToList(); // Init total DatStatistics totalStats = new DatStatistics { Statistics = new ItemDictionary(), DisplayName = "DIR: All DATs", MachineCount = 0, IsDirectory = true, }; // Init directory-level variables string lastdir = null; DatStatistics dirStats = new DatStatistics { Statistics = new ItemDictionary(), MachineCount = 0, IsDirectory = true, }; // Now process each of the input files foreach (ParentablePath file in files) { // Get the directory for the current file string thisdir = Path.GetDirectoryName(file.CurrentPath); // If we don't have the first file and the directory has changed, show the previous directory stats and reset if (lastdir != null && thisdir != lastdir && single) { dirStats.DisplayName = $"DIR: {WebUtility.HtmlEncode(lastdir)}"; dirStats.MachineCount = dirStats.Statistics.GameCount; stats.Add(dirStats); dirStats = new DatStatistics { Statistics = new ItemDictionary(), MachineCount = 0, IsDirectory = true, }; } InternalStopwatch watch = new InternalStopwatch($"Collecting statistics for '{file.CurrentPath}'"); List <string> machines = new List <string>(); DatFile datdata = Parser.CreateAndParse(file.CurrentPath, statsOnly: true, throwOnError: throwOnError); datdata.Items.BucketBy(ItemKey.Machine, DedupeType.None, norename: true); // Add single DAT stats (if asked) if (single) { DatStatistics individualStats = new DatStatistics { Statistics = datdata.Items, DisplayName = datdata.Header.FileName, MachineCount = datdata.Items.Keys.Count, IsDirectory = false, }; stats.Add(individualStats); } // Add single DAT stats to dir dirStats.Statistics.AddStatistics(datdata.Items); dirStats.Statistics.GameCount += datdata.Items.Keys.Count(); // Add single DAT stats to totals totalStats.Statistics.AddStatistics(datdata.Items); totalStats.Statistics.GameCount += datdata.Items.Keys.Count(); // Make sure to assign the new directory lastdir = thisdir; watch.Stop(); } // Add last directory stats if (single) { dirStats.DisplayName = $"DIR: {WebUtility.HtmlEncode(lastdir)}"; dirStats.MachineCount = dirStats.Statistics.GameCount; stats.Add(dirStats); } // Add total DAT stats totalStats.MachineCount = totalStats.Statistics.GameCount; stats.Add(totalStats); return(stats); }
/// <inheritdoc/> public override bool WriteToFile(string outfile, bool baddumpCol, bool nodumpCol, bool throwOnError = false) { InternalStopwatch watch = new InternalStopwatch($"Writing statistics to '{outfile}"); try { // Try to create the output file FileStream fs = File.Create(outfile); if (fs == null) { logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable"); return(false); } XmlTextWriter xtw = new XmlTextWriter(fs, Encoding.UTF8) { Formatting = Formatting.Indented, IndentChar = '\t', Indentation = 1 }; // Write out the header WriteHeader(xtw, baddumpCol, nodumpCol); // Now process each of the statistics for (int i = 0; i < Statistics.Count; i++) { // Get the current statistic DatStatistics stat = Statistics[i]; // If we have a directory statistic if (stat.IsDirectory) { WriteMidSeparator(xtw, baddumpCol, nodumpCol); WriteIndividual(xtw, stat, baddumpCol, nodumpCol); // If we have anything but the last value, write the separator if (i < Statistics.Count - 1) { WriteFooterSeparator(xtw, baddumpCol, nodumpCol); WriteMidHeader(xtw, baddumpCol, nodumpCol); } } // If we have a normal statistic else { WriteIndividual(xtw, stat, baddumpCol, nodumpCol); } } WriteFooter(xtw); xtw.Dispose(); fs.Dispose(); } catch (Exception ex) when(!throwOnError) { logger.Error(ex); return(false); } finally { watch.Stop(); } return(true); }
/// <summary> /// Write a single set of statistics /// </summary> /// <param name="xtw">XmlTextWriter to write to</param> /// <param name="stat">DatStatistics object to write out</param> /// <param name="baddumpCol">True if baddumps should be included in output, false otherwise</param> /// <param name="nodumpCol">True if nodumps should be included in output, false otherwise</param> private void WriteIndividual(XmlTextWriter xtw, DatStatistics stat, bool baddumpCol, bool nodumpCol) { bool isDirectory = stat.DisplayName.StartsWith("DIR: "); xtw.WriteStartElement("tr"); if (isDirectory) { xtw.WriteAttributeString("class", "dir"); } xtw.WriteElementString("td", isDirectory ? WebUtility.HtmlEncode(stat.DisplayName.Remove(0, 5)) : WebUtility.HtmlEncode(stat.DisplayName)); xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(GetBytesReadable(stat.Statistics.TotalSize)); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.MachineCount.ToString()); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.RomCount.ToString()); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.DiskCount.ToString()); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.CRCCount.ToString()); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.MD5Count.ToString()); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.SHA1Count.ToString()); xtw.WriteEndElement(); // td xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.SHA256Count.ToString()); xtw.WriteEndElement(); // td if (baddumpCol) { xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.BaddumpCount.ToString()); xtw.WriteEndElement(); // td } if (nodumpCol) { xtw.WriteStartElement("td"); xtw.WriteAttributeString("align", "right"); xtw.WriteString(stat.Statistics.NodumpCount.ToString()); xtw.WriteEndElement(); // td } xtw.WriteEndElement(); // tr xtw.Flush(); }