mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Consolidate statistics into a single place again
This commit is contained in:
@@ -296,7 +296,7 @@ namespace SabreTools.DatFiles
|
|||||||
if (statsOnly)
|
if (statsOnly)
|
||||||
{
|
{
|
||||||
Items.EnsureKey(key);
|
Items.EnsureKey(key);
|
||||||
Items.AddItemStatistics(item);
|
Items.DatStatistics.AddItemStatistics(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
411
SabreTools.DatFiles/DatStatistics.cs
Normal file
411
SabreTools.DatFiles/DatStatistics.cs
Normal file
@@ -0,0 +1,411 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using SabreTools.Core.Tools;
|
||||||
|
using SabreTools.DatItems;
|
||||||
|
using SabreTools.DatItems.Formats;
|
||||||
|
using SabreTools.Hashing;
|
||||||
|
|
||||||
|
namespace SabreTools.DatFiles
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Statistics wrapper for outputting
|
||||||
|
/// </summary>
|
||||||
|
public class DatStatistics
|
||||||
|
{
|
||||||
|
#region Private instance variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock for statistics calculation
|
||||||
|
/// </summary>
|
||||||
|
private readonly object statsLock = new();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overall item count
|
||||||
|
/// </summary>
|
||||||
|
public long TotalCount { get; private set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of items for each item type
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<ItemType, long> ItemCounts { get; private set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of machines
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Special count only used by statistics output</remarks>
|
||||||
|
public long GameCount { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total uncompressed size
|
||||||
|
/// </summary>
|
||||||
|
public long TotalSize { get; private set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of items for each hash type
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<HashType, long> HashCounts { get; private set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of items for each item status
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<ItemStatus, long> StatusCounts { get; private set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of items with the remove flag
|
||||||
|
/// </summary>
|
||||||
|
public long RemovedCount { get; private set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name to display on output
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total machine count to use on output
|
||||||
|
/// </summary>
|
||||||
|
public long MachineCount { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if statistics are for a directory or not
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDirectory { get; set; } = false;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Accessors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add to the statistics given a DatItem
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Item to add info from</param>
|
||||||
|
public void AddItemStatistics(DatItem item)
|
||||||
|
{
|
||||||
|
lock (statsLock)
|
||||||
|
{
|
||||||
|
// No matter what the item is, we increment the count
|
||||||
|
TotalCount++;
|
||||||
|
|
||||||
|
// Increment removal count
|
||||||
|
if (item.GetBoolFieldValue(DatItem.RemoveKey) == true)
|
||||||
|
RemovedCount++;
|
||||||
|
|
||||||
|
// Increment the item count for the type
|
||||||
|
AddItemCount(item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>());
|
||||||
|
|
||||||
|
// Some item types require special processing
|
||||||
|
switch (item)
|
||||||
|
{
|
||||||
|
case Disk disk:
|
||||||
|
if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
||||||
|
{
|
||||||
|
AddHashCount(HashType.MD5, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key)) ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddStatusCount(ItemStatus.BadDump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
||||||
|
AddStatusCount(ItemStatus.Good, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
||||||
|
AddStatusCount(ItemStatus.Nodump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
||||||
|
AddStatusCount(ItemStatus.Verified, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
||||||
|
break;
|
||||||
|
case Media media:
|
||||||
|
AddHashCount(HashType.MD5, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA256, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SpamSum, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SpamSumKey)) ? 0 : 1);
|
||||||
|
break;
|
||||||
|
case Rom rom:
|
||||||
|
if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
||||||
|
{
|
||||||
|
TotalSize += rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) ?? 0;
|
||||||
|
AddHashCount(HashType.CRC32, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.MD5, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA256, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key)) ? 0 : 1);
|
||||||
|
AddHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SpamSumKey)) ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddStatusCount(ItemStatus.BadDump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
||||||
|
AddStatusCount(ItemStatus.Good, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
||||||
|
AddStatusCount(ItemStatus.Nodump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
||||||
|
AddStatusCount(ItemStatus.Verified, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add statistics from another DatStatistics object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stats">DatStatistics object to add from</param>
|
||||||
|
public void AddStatistics(DatStatistics stats)
|
||||||
|
{
|
||||||
|
TotalCount += stats.TotalCount;
|
||||||
|
|
||||||
|
// Loop through and add stats for all items
|
||||||
|
foreach (var itemCountKvp in stats.ItemCounts)
|
||||||
|
{
|
||||||
|
AddItemCount(itemCountKvp.Key, itemCountKvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameCount += stats.GameCount;
|
||||||
|
|
||||||
|
TotalSize += stats.TotalSize;
|
||||||
|
|
||||||
|
// Individual hash counts
|
||||||
|
foreach (var hashCountKvp in stats.HashCounts)
|
||||||
|
{
|
||||||
|
AddHashCount(hashCountKvp.Key, hashCountKvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual status counts
|
||||||
|
foreach (var statusCountKvp in stats.StatusCounts)
|
||||||
|
{
|
||||||
|
AddStatusCount(statusCountKvp.Key, statusCountKvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemovedCount += stats.RemovedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the item count for a given hash type, defaulting to 0 if it does not exist
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hashType">Hash type to retrieve</param>
|
||||||
|
/// <returns>The number of items with that hash, if it exists</returns>
|
||||||
|
public long GetHashCount(HashType hashType)
|
||||||
|
{
|
||||||
|
lock (HashCounts)
|
||||||
|
{
|
||||||
|
if (!HashCounts.ContainsKey(hashType))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return HashCounts[hashType];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the item count for a given item type, defaulting to 0 if it does not exist
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemType">Item type to retrieve</param>
|
||||||
|
/// <returns>The number of items of that type, if it exists</returns>
|
||||||
|
public long GetItemCount(ItemType itemType)
|
||||||
|
{
|
||||||
|
lock (ItemCounts)
|
||||||
|
{
|
||||||
|
if (!ItemCounts.ContainsKey(itemType))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ItemCounts[itemType];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the item count for a given item status, defaulting to 0 if it does not exist
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemStatus">Item status to retrieve</param>
|
||||||
|
/// <returns>The number of items of that type, if it exists</returns>
|
||||||
|
public long GetStatusCount(ItemStatus itemStatus)
|
||||||
|
{
|
||||||
|
lock (StatusCounts)
|
||||||
|
{
|
||||||
|
if (!StatusCounts.ContainsKey(itemStatus))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return StatusCounts[itemStatus];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Increment the hash count for a given hash type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hashType">Hash type to increment</param>
|
||||||
|
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
||||||
|
private void AddHashCount(HashType hashType, long interval = 1)
|
||||||
|
{
|
||||||
|
lock (HashCounts)
|
||||||
|
{
|
||||||
|
if (!HashCounts.ContainsKey(hashType))
|
||||||
|
HashCounts[hashType] = 0;
|
||||||
|
|
||||||
|
HashCounts[hashType] += interval;
|
||||||
|
if (HashCounts[hashType] < 0)
|
||||||
|
HashCounts[hashType] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Increment the item count for a given item type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemType">Item type to increment</param>
|
||||||
|
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
||||||
|
private void AddItemCount(ItemType itemType, long interval = 1)
|
||||||
|
{
|
||||||
|
lock (ItemCounts)
|
||||||
|
{
|
||||||
|
if (!ItemCounts.ContainsKey(itemType))
|
||||||
|
ItemCounts[itemType] = 0;
|
||||||
|
|
||||||
|
ItemCounts[itemType] += interval;
|
||||||
|
if (ItemCounts[itemType] < 0)
|
||||||
|
ItemCounts[itemType] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Increment the item count for a given item status
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemStatus">Item type to increment</param>
|
||||||
|
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
||||||
|
private void AddStatusCount(ItemStatus itemStatus, long interval = 1)
|
||||||
|
{
|
||||||
|
lock (StatusCounts)
|
||||||
|
{
|
||||||
|
if (!StatusCounts.ContainsKey(itemStatus))
|
||||||
|
StatusCounts[itemStatus] = 0;
|
||||||
|
|
||||||
|
StatusCounts[itemStatus] += interval;
|
||||||
|
if (StatusCounts[itemStatus] < 0)
|
||||||
|
StatusCounts[itemStatus] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove from the statistics given a DatItem
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Item to remove info for</param>
|
||||||
|
public void RemoveItemStatistics(DatItem item)
|
||||||
|
{
|
||||||
|
// If we have a null item, we can't do anything
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (statsLock)
|
||||||
|
{
|
||||||
|
// No matter what the item is, we decrease the count
|
||||||
|
TotalCount--;
|
||||||
|
|
||||||
|
// Decrement removal count
|
||||||
|
if (item.GetBoolFieldValue(DatItem.RemoveKey) == true)
|
||||||
|
RemovedCount--;
|
||||||
|
|
||||||
|
// Decrement the item count for the type
|
||||||
|
RemoveItemCount(item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>());
|
||||||
|
|
||||||
|
// Some item types require special processing
|
||||||
|
switch (item)
|
||||||
|
{
|
||||||
|
case Disk disk:
|
||||||
|
if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
||||||
|
{
|
||||||
|
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key)) ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveStatusCount(ItemStatus.BadDump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
||||||
|
RemoveStatusCount(ItemStatus.Good, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
||||||
|
RemoveStatusCount(ItemStatus.Nodump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
||||||
|
RemoveStatusCount(ItemStatus.Verified, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
||||||
|
break;
|
||||||
|
case Media media:
|
||||||
|
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA256, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SpamSum, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SpamSumKey)) ? 0 : 1);
|
||||||
|
break;
|
||||||
|
case Rom rom:
|
||||||
|
if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
||||||
|
{
|
||||||
|
TotalSize -= rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) ?? 0;
|
||||||
|
RemoveHashCount(HashType.CRC32, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA256, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key)) ? 0 : 1);
|
||||||
|
RemoveHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SpamSumKey)) ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveStatusCount(ItemStatus.BadDump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
||||||
|
RemoveStatusCount(ItemStatus.Good, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
||||||
|
RemoveStatusCount(ItemStatus.Nodump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
||||||
|
RemoveStatusCount(ItemStatus.Verified, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset all statistics
|
||||||
|
/// </summary>
|
||||||
|
public void ResetStatistics()
|
||||||
|
{
|
||||||
|
TotalCount = 0;
|
||||||
|
ItemCounts = [];
|
||||||
|
GameCount = 0;
|
||||||
|
TotalSize = 0;
|
||||||
|
HashCounts = [];
|
||||||
|
StatusCounts = [];
|
||||||
|
RemovedCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrement the hash count for a given hash type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hashType">Hash type to increment</param>
|
||||||
|
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
||||||
|
private void RemoveHashCount(HashType hashType, long interval = 1)
|
||||||
|
{
|
||||||
|
lock (HashCounts)
|
||||||
|
{
|
||||||
|
if (!HashCounts.ContainsKey(hashType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
HashCounts[hashType] -= interval;
|
||||||
|
if (HashCounts[hashType] < 0)
|
||||||
|
HashCounts[hashType] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrement the item count for a given item type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemType">Item type to decrement</param>
|
||||||
|
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
||||||
|
private void RemoveItemCount(ItemType itemType, long interval = 1)
|
||||||
|
{
|
||||||
|
lock (ItemCounts)
|
||||||
|
{
|
||||||
|
if (!ItemCounts.ContainsKey(itemType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemCounts[itemType] -= interval;
|
||||||
|
if (ItemCounts[itemType] < 0)
|
||||||
|
ItemCounts[itemType] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrement the item count for a given item status
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemStatus">Item type to decrement</param>
|
||||||
|
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
||||||
|
private void RemoveStatusCount(ItemStatus itemStatus, long interval = 1)
|
||||||
|
{
|
||||||
|
lock (StatusCounts)
|
||||||
|
{
|
||||||
|
if (!StatusCounts.ContainsKey(itemStatus))
|
||||||
|
return;
|
||||||
|
|
||||||
|
StatusCounts[itemStatus] -= interval;
|
||||||
|
if (StatusCounts[itemStatus] < 0)
|
||||||
|
StatusCounts[itemStatus] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@ using System.Threading.Tasks;
|
|||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SabreTools.Core;
|
using SabreTools.Core;
|
||||||
using SabreTools.Core.Tools;
|
|
||||||
using SabreTools.DatItems;
|
using SabreTools.DatItems;
|
||||||
using SabreTools.DatItems.Formats;
|
using SabreTools.DatItems.Formats;
|
||||||
using SabreTools.Hashing;
|
using SabreTools.Hashing;
|
||||||
@@ -50,11 +49,6 @@ namespace SabreTools.DatFiles
|
|||||||
private readonly Dictionary<string, ConcurrentList<DatItem>?> items;
|
private readonly Dictionary<string, ConcurrentList<DatItem>?> items;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Lock for statistics calculation
|
|
||||||
/// </summary>
|
|
||||||
private readonly object statsLock = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logging object
|
/// Logging object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -96,47 +90,10 @@ namespace SabreTools.DatFiles
|
|||||||
#region Statistics
|
#region Statistics
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overall item count
|
/// DAT statistics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore, XmlIgnore]
|
[JsonIgnore, XmlIgnore]
|
||||||
public long TotalCount { get; private set; } = 0;
|
public DatStatistics DatStatistics { get; } = new DatStatistics();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items for each item type
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public Dictionary<ItemType, long> ItemCounts { get; private set; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of machines
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Special count only used by statistics output</remarks>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public long GameCount { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Total uncompressed size
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public long TotalSize { get; private set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items for each hash type
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public Dictionary<HashType, long> HashCounts { get; private set; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items for each item status
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public Dictionary<ItemStatus, long> StatusCounts { get; private set; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items with the remove flag
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public long RemovedCount { get; private set; } = 0;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -193,7 +150,7 @@ namespace SabreTools.DatFiles
|
|||||||
items[key]!.Add(value);
|
items[key]!.Add(value);
|
||||||
|
|
||||||
// Now update the statistics
|
// Now update the statistics
|
||||||
AddItemStatistics(value);
|
DatStatistics.AddItemStatistics(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,67 +164,6 @@ namespace SabreTools.DatFiles
|
|||||||
AddRange(key, value);
|
AddRange(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add to the statistics given a DatItem
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">Item to add info from</param>
|
|
||||||
public void AddItemStatistics(DatItem item)
|
|
||||||
{
|
|
||||||
lock (statsLock)
|
|
||||||
{
|
|
||||||
// No matter what the item is, we increment the count
|
|
||||||
TotalCount++;
|
|
||||||
|
|
||||||
// Increment removal count
|
|
||||||
if (item.GetBoolFieldValue(DatItem.RemoveKey) == true)
|
|
||||||
RemovedCount++;
|
|
||||||
|
|
||||||
// Increment the item count for the type
|
|
||||||
AddItemCount(item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>());
|
|
||||||
|
|
||||||
// Some item types require special processing
|
|
||||||
switch (item)
|
|
||||||
{
|
|
||||||
case Disk disk:
|
|
||||||
if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
AddHashCount(HashType.MD5, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddStatusCount(ItemStatus.BadDump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Good, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Nodump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Verified, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
case Media media:
|
|
||||||
AddHashCount(HashType.MD5, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA256, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SpamSum, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SpamSumKey)) ? 0 : 1);
|
|
||||||
break;
|
|
||||||
case Rom rom:
|
|
||||||
if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
TotalSize += rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) ?? 0;
|
|
||||||
AddHashCount(HashType.CRC32, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.MD5, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA256, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SpamSumKey)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddStatusCount(ItemStatus.BadDump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Good, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Nodump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Verified, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a range of values to the file dictionary
|
/// Add a range of values to the file dictionary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -291,44 +187,11 @@ namespace SabreTools.DatFiles
|
|||||||
// Now update the statistics
|
// Now update the statistics
|
||||||
foreach (DatItem item in value)
|
foreach (DatItem item in value)
|
||||||
{
|
{
|
||||||
AddItemStatistics(item);
|
DatStatistics.AddItemStatistics(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add statistics from another DatStats object
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stats">DatStats object to add from</param>
|
|
||||||
public void AddStatistics(ItemDictionary stats)
|
|
||||||
{
|
|
||||||
TotalCount += stats.Count;
|
|
||||||
|
|
||||||
// Loop through and add stats for all items
|
|
||||||
foreach (var itemCountKvp in stats.ItemCounts)
|
|
||||||
{
|
|
||||||
AddItemCount(itemCountKvp.Key, itemCountKvp.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameCount += stats.GameCount;
|
|
||||||
|
|
||||||
TotalSize += stats.TotalSize;
|
|
||||||
|
|
||||||
// Individual hash counts
|
|
||||||
foreach (var hashCountKvp in stats.HashCounts)
|
|
||||||
{
|
|
||||||
AddHashCount(hashCountKvp.Key, hashCountKvp.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Individual status counts
|
|
||||||
foreach (var statusCountKvp in stats.StatusCounts)
|
|
||||||
{
|
|
||||||
AddStatusCount(statusCountKvp.Key, statusCountKvp.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemovedCount += stats.RemovedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get if the file dictionary contains the key
|
/// Get if the file dictionary contains the key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -421,7 +284,7 @@ namespace SabreTools.DatFiles
|
|||||||
// Remove the statistics first
|
// Remove the statistics first
|
||||||
foreach (DatItem item in items[key]!)
|
foreach (DatItem item in items[key]!)
|
||||||
{
|
{
|
||||||
RemoveItemStatistics(item);
|
DatStatistics.RemoveItemStatistics(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the key from the dictionary
|
// Remove the key from the dictionary
|
||||||
@@ -448,7 +311,7 @@ namespace SabreTools.DatFiles
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove the statistics first
|
// Remove the statistics first
|
||||||
RemoveItemStatistics(value);
|
DatStatistics.RemoveItemStatistics(value);
|
||||||
|
|
||||||
return items[key]!.Remove(value);
|
return items[key]!.Remove(value);
|
||||||
}
|
}
|
||||||
@@ -467,7 +330,7 @@ namespace SabreTools.DatFiles
|
|||||||
// Remove the statistics first
|
// Remove the statistics first
|
||||||
foreach (DatItem item in items[key]!)
|
foreach (DatItem item in items[key]!)
|
||||||
{
|
{
|
||||||
RemoveItemStatistics(item);
|
DatStatistics.RemoveItemStatistics(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the key from the dictionary
|
// Remove the key from the dictionary
|
||||||
@@ -484,227 +347,6 @@ namespace SabreTools.DatFiles
|
|||||||
bucketedBy = newBucket;
|
bucketedBy = newBucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remove from the statistics given a DatItem
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">Item to remove info for</param>
|
|
||||||
public void RemoveItemStatistics(DatItem item)
|
|
||||||
{
|
|
||||||
// If we have a null item, we can't do anything
|
|
||||||
if (item == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lock (statsLock)
|
|
||||||
{
|
|
||||||
// No matter what the item is, we decrease the count
|
|
||||||
TotalCount--;
|
|
||||||
|
|
||||||
// Decrement removal count
|
|
||||||
if (item.GetBoolFieldValue(DatItem.RemoveKey) == true)
|
|
||||||
RemovedCount--;
|
|
||||||
|
|
||||||
// Decrement the item count for the type
|
|
||||||
RemoveItemCount(item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>());
|
|
||||||
|
|
||||||
// Some item types require special processing
|
|
||||||
switch (item)
|
|
||||||
{
|
|
||||||
case Disk disk:
|
|
||||||
if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveStatusCount(ItemStatus.BadDump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Good, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Nodump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Verified, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
case Media media:
|
|
||||||
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA256, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SpamSum, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SpamSumKey)) ? 0 : 1);
|
|
||||||
break;
|
|
||||||
case Rom rom:
|
|
||||||
if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
TotalSize -= rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) ?? 0;
|
|
||||||
RemoveHashCount(HashType.CRC32, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA256, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SpamSumKey)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveStatusCount(ItemStatus.BadDump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Good, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Nodump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Verified, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the item count for a given hash type, defaulting to 0 if it does not exist
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hashType">Hash type to retrieve</param>
|
|
||||||
/// <returns>The number of items with that hash, if it exists</returns>
|
|
||||||
public long GetHashCount(HashType hashType)
|
|
||||||
{
|
|
||||||
lock (HashCounts)
|
|
||||||
{
|
|
||||||
if (!HashCounts.ContainsKey(hashType))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return HashCounts[hashType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the item count for a given item type, defaulting to 0 if it does not exist
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemType">Item type to retrieve</param>
|
|
||||||
/// <returns>The number of items of that type, if it exists</returns>
|
|
||||||
public long GetItemCount(ItemType itemType)
|
|
||||||
{
|
|
||||||
lock (ItemCounts)
|
|
||||||
{
|
|
||||||
if (!ItemCounts.ContainsKey(itemType))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ItemCounts[itemType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the item count for a given item status, defaulting to 0 if it does not exist
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStatus">Item status to retrieve</param>
|
|
||||||
/// <returns>The number of items of that type, if it exists</returns>
|
|
||||||
public long GetStatusCount(ItemStatus itemStatus)
|
|
||||||
{
|
|
||||||
lock (StatusCounts)
|
|
||||||
{
|
|
||||||
if (!StatusCounts.ContainsKey(itemStatus))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return StatusCounts[itemStatus];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increment the hash count for a given hash type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hashType">Hash type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void AddHashCount(HashType hashType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (HashCounts)
|
|
||||||
{
|
|
||||||
if (!HashCounts.ContainsKey(hashType))
|
|
||||||
HashCounts[hashType] = 0;
|
|
||||||
|
|
||||||
HashCounts[hashType] += interval;
|
|
||||||
if (HashCounts[hashType] < 0)
|
|
||||||
HashCounts[hashType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrement the hash count for a given hash type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hashType">Hash type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void RemoveHashCount(HashType hashType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (HashCounts)
|
|
||||||
{
|
|
||||||
if (!HashCounts.ContainsKey(hashType))
|
|
||||||
return;
|
|
||||||
|
|
||||||
HashCounts[hashType] -= interval;
|
|
||||||
if (HashCounts[hashType] < 0)
|
|
||||||
HashCounts[hashType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increment the item count for a given item type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemType">Item type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void AddItemCount(ItemType itemType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (ItemCounts)
|
|
||||||
{
|
|
||||||
if (!ItemCounts.ContainsKey(itemType))
|
|
||||||
ItemCounts[itemType] = 0;
|
|
||||||
|
|
||||||
ItemCounts[itemType] += interval;
|
|
||||||
if (ItemCounts[itemType] < 0)
|
|
||||||
ItemCounts[itemType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrement the item count for a given item type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemType">Item type to decrement</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void RemoveItemCount(ItemType itemType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (ItemCounts)
|
|
||||||
{
|
|
||||||
if (!ItemCounts.ContainsKey(itemType))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ItemCounts[itemType] -= interval;
|
|
||||||
if (ItemCounts[itemType] < 0)
|
|
||||||
ItemCounts[itemType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increment the item count for a given item status
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStatus">Item type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void AddStatusCount(ItemStatus itemStatus, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (StatusCounts)
|
|
||||||
{
|
|
||||||
if (!StatusCounts.ContainsKey(itemStatus))
|
|
||||||
StatusCounts[itemStatus] = 0;
|
|
||||||
|
|
||||||
StatusCounts[itemStatus] += interval;
|
|
||||||
if (StatusCounts[itemStatus] < 0)
|
|
||||||
StatusCounts[itemStatus] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrement the item count for a given item status
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStatus">Item type to decrement</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void RemoveStatusCount(ItemStatus itemStatus, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (StatusCounts)
|
|
||||||
{
|
|
||||||
if (!StatusCounts.ContainsKey(itemStatus))
|
|
||||||
return;
|
|
||||||
|
|
||||||
StatusCounts[itemStatus] -= interval;
|
|
||||||
if (StatusCounts[itemStatus] < 0)
|
|
||||||
StatusCounts[itemStatus] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
@@ -925,7 +567,7 @@ namespace SabreTools.DatFiles
|
|||||||
ConcurrentList<DatItem> output = [];
|
ConcurrentList<DatItem> output = [];
|
||||||
|
|
||||||
// Check for an empty rom list first
|
// Check for an empty rom list first
|
||||||
if (TotalCount == 0)
|
if (DatStatistics.TotalCount == 0)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
// We want to get the proper key for the DatItem
|
// We want to get the proper key for the DatItem
|
||||||
@@ -975,7 +617,7 @@ namespace SabreTools.DatFiles
|
|||||||
public bool HasDuplicates(DatItem datItem, bool sorted = false)
|
public bool HasDuplicates(DatItem datItem, bool sorted = false)
|
||||||
{
|
{
|
||||||
// Check for an empty rom list first
|
// Check for an empty rom list first
|
||||||
if (TotalCount == 0)
|
if (DatStatistics.TotalCount == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We want to get the proper key for the DatItem
|
// We want to get the proper key for the DatItem
|
||||||
@@ -996,7 +638,7 @@ namespace SabreTools.DatFiles
|
|||||||
public void RecalculateStats()
|
public void RecalculateStats()
|
||||||
{
|
{
|
||||||
// Wipe out any stats already there
|
// Wipe out any stats already there
|
||||||
ResetStatistics();
|
DatStatistics.ResetStatistics();
|
||||||
|
|
||||||
// If we have a blank Dat in any way, return
|
// If we have a blank Dat in any way, return
|
||||||
if (items == null)
|
if (items == null)
|
||||||
@@ -1011,54 +653,40 @@ namespace SabreTools.DatFiles
|
|||||||
|
|
||||||
foreach (DatItem item in datItems)
|
foreach (DatItem item in datItems)
|
||||||
{
|
{
|
||||||
AddItemStatistics(item);
|
DatStatistics.AddItemStatistics(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reset all statistics
|
|
||||||
/// </summary>
|
|
||||||
public void ResetStatistics()
|
|
||||||
{
|
|
||||||
TotalCount = 0;
|
|
||||||
ItemCounts = [];
|
|
||||||
GameCount = 0;
|
|
||||||
TotalSize = 0;
|
|
||||||
HashCounts = [];
|
|
||||||
StatusCounts = [];
|
|
||||||
RemovedCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the highest-order Field value that represents the statistics
|
/// Get the highest-order Field value that represents the statistics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ItemKey GetBestAvailable()
|
private ItemKey GetBestAvailable()
|
||||||
{
|
{
|
||||||
// Get the required counts
|
// Get the required counts
|
||||||
long diskCount = GetItemCount(ItemType.Disk);
|
long diskCount = DatStatistics.GetItemCount(ItemType.Disk);
|
||||||
long mediaCount = GetItemCount(ItemType.Media);
|
long mediaCount = DatStatistics.GetItemCount(ItemType.Media);
|
||||||
long romCount = GetItemCount(ItemType.Rom);
|
long romCount = DatStatistics.GetItemCount(ItemType.Rom);
|
||||||
long nodumpCount = GetStatusCount(ItemStatus.Nodump);
|
long nodumpCount = DatStatistics.GetStatusCount(ItemStatus.Nodump);
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-512, we bucket by that
|
// If all items are supposed to have a SHA-512, we bucket by that
|
||||||
if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA512))
|
if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA512))
|
||||||
return ItemKey.SHA512;
|
return ItemKey.SHA512;
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-384, we bucket by that
|
// If all items are supposed to have a SHA-384, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA384))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA384))
|
||||||
return ItemKey.SHA384;
|
return ItemKey.SHA384;
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-256, we bucket by that
|
// If all items are supposed to have a SHA-256, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA256))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA256))
|
||||||
return ItemKey.SHA256;
|
return ItemKey.SHA256;
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-1, we bucket by that
|
// If all items are supposed to have a SHA-1, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA1))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA1))
|
||||||
return ItemKey.SHA1;
|
return ItemKey.SHA1;
|
||||||
|
|
||||||
// If all items are supposed to have a MD5, we bucket by that
|
// If all items are supposed to have a MD5, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.MD5))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.MD5))
|
||||||
return ItemKey.MD5;
|
return ItemKey.MD5;
|
||||||
|
|
||||||
// Otherwise, we bucket by CRC
|
// Otherwise, we bucket by CRC
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ using System.Threading.Tasks;
|
|||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SabreTools.Core;
|
using SabreTools.Core;
|
||||||
using SabreTools.Core.Tools;
|
|
||||||
using SabreTools.DatItems;
|
using SabreTools.DatItems;
|
||||||
using SabreTools.DatItems.Formats;
|
using SabreTools.DatItems.Formats;
|
||||||
using SabreTools.Hashing;
|
using SabreTools.Hashing;
|
||||||
@@ -55,11 +54,6 @@ namespace SabreTools.DatFiles
|
|||||||
private readonly Dictionary<string, Machine> machines;
|
private readonly Dictionary<string, Machine> machines;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Lock for statistics calculation
|
|
||||||
/// </summary>
|
|
||||||
private readonly object statsLock = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logging object
|
/// Logging object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -101,47 +95,10 @@ namespace SabreTools.DatFiles
|
|||||||
#region Statistics
|
#region Statistics
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overall item count
|
/// DAT statistics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore, XmlIgnore]
|
[JsonIgnore, XmlIgnore]
|
||||||
public long TotalCount { get; private set; } = 0;
|
public DatStatistics DatStatistics { get; } = new DatStatistics();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items for each item type
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public Dictionary<ItemType, long> ItemCounts { get; private set; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of machines
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Special count only used by statistics output</remarks>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public long GameCount { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Total uncompressed size
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public long TotalSize { get; private set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items for each hash type
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public Dictionary<HashType, long> HashCounts { get; private set; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items for each item status
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public Dictionary<ItemStatus, long> StatusCounts { get; private set; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of items with the remove flag
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore, XmlIgnore]
|
|
||||||
public long RemovedCount { get; private set; } = 0;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -198,7 +155,7 @@ namespace SabreTools.DatFiles
|
|||||||
items[key]!.Add(value);
|
items[key]!.Add(value);
|
||||||
|
|
||||||
// Now update the statistics
|
// Now update the statistics
|
||||||
AddItemStatistics(value);
|
DatStatistics.AddItemStatistics(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,67 +169,6 @@ namespace SabreTools.DatFiles
|
|||||||
AddRange(key, value);
|
AddRange(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add to the statistics given a DatItem
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">Item to add info from</param>
|
|
||||||
public void AddItemStatistics(DatItem item)
|
|
||||||
{
|
|
||||||
lock (statsLock)
|
|
||||||
{
|
|
||||||
// No matter what the item is, we increment the count
|
|
||||||
TotalCount++;
|
|
||||||
|
|
||||||
// Increment removal count
|
|
||||||
if (item.GetBoolFieldValue(DatItem.RemoveKey) == true)
|
|
||||||
RemovedCount++;
|
|
||||||
|
|
||||||
// Increment the item count for the type
|
|
||||||
AddItemCount(item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>());
|
|
||||||
|
|
||||||
// Some item types require special processing
|
|
||||||
switch (item)
|
|
||||||
{
|
|
||||||
case Disk disk:
|
|
||||||
if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
AddHashCount(HashType.MD5, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddStatusCount(ItemStatus.BadDump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Good, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Nodump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Verified, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
case Media media:
|
|
||||||
AddHashCount(HashType.MD5, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA256, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SpamSum, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SpamSumKey)) ? 0 : 1);
|
|
||||||
break;
|
|
||||||
case Rom rom:
|
|
||||||
if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
TotalSize += rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) ?? 0;
|
|
||||||
AddHashCount(HashType.CRC32, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.MD5, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA1, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA256, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key)) ? 0 : 1);
|
|
||||||
AddHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SpamSumKey)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddStatusCount(ItemStatus.BadDump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Good, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Nodump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
AddStatusCount(ItemStatus.Verified, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a range of values to the file dictionary
|
/// Add a range of values to the file dictionary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -296,44 +192,11 @@ namespace SabreTools.DatFiles
|
|||||||
// Now update the statistics
|
// Now update the statistics
|
||||||
foreach (DatItem item in value)
|
foreach (DatItem item in value)
|
||||||
{
|
{
|
||||||
AddItemStatistics(item);
|
DatStatistics.AddItemStatistics(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add statistics from another DatStats object
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stats">DatStats object to add from</param>
|
|
||||||
public void AddStatistics(ItemDictionary stats)
|
|
||||||
{
|
|
||||||
TotalCount += stats.Count;
|
|
||||||
|
|
||||||
// Loop through and add stats for all items
|
|
||||||
foreach (var itemCountKvp in stats.ItemCounts)
|
|
||||||
{
|
|
||||||
AddItemCount(itemCountKvp.Key, itemCountKvp.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameCount += stats.GameCount;
|
|
||||||
|
|
||||||
TotalSize += stats.TotalSize;
|
|
||||||
|
|
||||||
// Individual hash counts
|
|
||||||
foreach (var hashCountKvp in stats.HashCounts)
|
|
||||||
{
|
|
||||||
AddHashCount(hashCountKvp.Key, hashCountKvp.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Individual status counts
|
|
||||||
foreach (var statusCountKvp in stats.StatusCounts)
|
|
||||||
{
|
|
||||||
AddStatusCount(statusCountKvp.Key, statusCountKvp.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemovedCount += stats.RemovedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get if the file dictionary contains the key
|
/// Get if the file dictionary contains the key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -426,7 +289,7 @@ namespace SabreTools.DatFiles
|
|||||||
// Remove the statistics first
|
// Remove the statistics first
|
||||||
foreach (DatItem item in items[key]!)
|
foreach (DatItem item in items[key]!)
|
||||||
{
|
{
|
||||||
RemoveItemStatistics(item);
|
DatStatistics.RemoveItemStatistics(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the key from the dictionary
|
// Remove the key from the dictionary
|
||||||
@@ -453,7 +316,7 @@ namespace SabreTools.DatFiles
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove the statistics first
|
// Remove the statistics first
|
||||||
RemoveItemStatistics(value);
|
DatStatistics.RemoveItemStatistics(value);
|
||||||
|
|
||||||
return items[key]!.Remove(value);
|
return items[key]!.Remove(value);
|
||||||
}
|
}
|
||||||
@@ -472,7 +335,7 @@ namespace SabreTools.DatFiles
|
|||||||
// Remove the statistics first
|
// Remove the statistics first
|
||||||
foreach (DatItem item in items[key]!)
|
foreach (DatItem item in items[key]!)
|
||||||
{
|
{
|
||||||
RemoveItemStatistics(item);
|
DatStatistics.RemoveItemStatistics(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the key from the dictionary
|
// Remove the key from the dictionary
|
||||||
@@ -489,227 +352,6 @@ namespace SabreTools.DatFiles
|
|||||||
bucketedBy = newBucket;
|
bucketedBy = newBucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remove from the statistics given a DatItem
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">Item to remove info for</param>
|
|
||||||
public void RemoveItemStatistics(DatItem item)
|
|
||||||
{
|
|
||||||
// If we have a null item, we can't do anything
|
|
||||||
if (item == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lock (statsLock)
|
|
||||||
{
|
|
||||||
// No matter what the item is, we decrease the count
|
|
||||||
TotalCount--;
|
|
||||||
|
|
||||||
// Decrement removal count
|
|
||||||
if (item.GetBoolFieldValue(DatItem.RemoveKey) == true)
|
|
||||||
RemovedCount--;
|
|
||||||
|
|
||||||
// Decrement the item count for the type
|
|
||||||
RemoveItemCount(item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>());
|
|
||||||
|
|
||||||
// Some item types require special processing
|
|
||||||
switch (item)
|
|
||||||
{
|
|
||||||
case Disk disk:
|
|
||||||
if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveStatusCount(ItemStatus.BadDump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Good, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Nodump, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Verified, disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
case Media media:
|
|
||||||
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA256, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SpamSum, string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SpamSumKey)) ? 0 : 1);
|
|
||||||
break;
|
|
||||||
case Rom rom:
|
|
||||||
if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() != ItemStatus.Nodump)
|
|
||||||
{
|
|
||||||
TotalSize -= rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) ?? 0;
|
|
||||||
RemoveHashCount(HashType.CRC32, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.MD5, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA1, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA256, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key)) ? 0 : 1);
|
|
||||||
RemoveHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SpamSumKey)) ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveStatusCount(ItemStatus.BadDump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.BadDump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Good, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Good ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Nodump, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Nodump ? 1 : 0);
|
|
||||||
RemoveStatusCount(ItemStatus.Verified, rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue<ItemStatus>() == ItemStatus.Verified ? 1 : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the item count for a given hash type, defaulting to 0 if it does not exist
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hashType">Hash type to retrieve</param>
|
|
||||||
/// <returns>The number of items with that hash, if it exists</returns>
|
|
||||||
public long GetHashCount(HashType hashType)
|
|
||||||
{
|
|
||||||
lock (HashCounts)
|
|
||||||
{
|
|
||||||
if (!HashCounts.ContainsKey(hashType))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return HashCounts[hashType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the item count for a given item type, defaulting to 0 if it does not exist
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemType">Item type to retrieve</param>
|
|
||||||
/// <returns>The number of items of that type, if it exists</returns>
|
|
||||||
public long GetItemCount(ItemType itemType)
|
|
||||||
{
|
|
||||||
lock (ItemCounts)
|
|
||||||
{
|
|
||||||
if (!ItemCounts.ContainsKey(itemType))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ItemCounts[itemType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the item count for a given item status, defaulting to 0 if it does not exist
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStatus">Item status to retrieve</param>
|
|
||||||
/// <returns>The number of items of that type, if it exists</returns>
|
|
||||||
public long GetStatusCount(ItemStatus itemStatus)
|
|
||||||
{
|
|
||||||
lock (StatusCounts)
|
|
||||||
{
|
|
||||||
if (!StatusCounts.ContainsKey(itemStatus))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return StatusCounts[itemStatus];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increment the hash count for a given hash type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hashType">Hash type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void AddHashCount(HashType hashType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (HashCounts)
|
|
||||||
{
|
|
||||||
if (!HashCounts.ContainsKey(hashType))
|
|
||||||
HashCounts[hashType] = 0;
|
|
||||||
|
|
||||||
HashCounts[hashType] += interval;
|
|
||||||
if (HashCounts[hashType] < 0)
|
|
||||||
HashCounts[hashType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrement the hash count for a given hash type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hashType">Hash type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void RemoveHashCount(HashType hashType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (HashCounts)
|
|
||||||
{
|
|
||||||
if (!HashCounts.ContainsKey(hashType))
|
|
||||||
return;
|
|
||||||
|
|
||||||
HashCounts[hashType] -= interval;
|
|
||||||
if (HashCounts[hashType] < 0)
|
|
||||||
HashCounts[hashType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increment the item count for a given item type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemType">Item type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void AddItemCount(ItemType itemType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (ItemCounts)
|
|
||||||
{
|
|
||||||
if (!ItemCounts.ContainsKey(itemType))
|
|
||||||
ItemCounts[itemType] = 0;
|
|
||||||
|
|
||||||
ItemCounts[itemType] += interval;
|
|
||||||
if (ItemCounts[itemType] < 0)
|
|
||||||
ItemCounts[itemType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrement the item count for a given item type
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemType">Item type to decrement</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void RemoveItemCount(ItemType itemType, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (ItemCounts)
|
|
||||||
{
|
|
||||||
if (!ItemCounts.ContainsKey(itemType))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ItemCounts[itemType] -= interval;
|
|
||||||
if (ItemCounts[itemType] < 0)
|
|
||||||
ItemCounts[itemType] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increment the item count for a given item status
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStatus">Item type to increment</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void AddStatusCount(ItemStatus itemStatus, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (StatusCounts)
|
|
||||||
{
|
|
||||||
if (!StatusCounts.ContainsKey(itemStatus))
|
|
||||||
StatusCounts[itemStatus] = 0;
|
|
||||||
|
|
||||||
StatusCounts[itemStatus] += interval;
|
|
||||||
if (StatusCounts[itemStatus] < 0)
|
|
||||||
StatusCounts[itemStatus] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrement the item count for a given item status
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemStatus">Item type to decrement</param>
|
|
||||||
/// <param name="interval">Amount to increment by, defaults to 1</param>
|
|
||||||
private void RemoveStatusCount(ItemStatus itemStatus, long interval = 1)
|
|
||||||
{
|
|
||||||
lock (StatusCounts)
|
|
||||||
{
|
|
||||||
if (!StatusCounts.ContainsKey(itemStatus))
|
|
||||||
return;
|
|
||||||
|
|
||||||
StatusCounts[itemStatus] -= interval;
|
|
||||||
if (StatusCounts[itemStatus] < 0)
|
|
||||||
StatusCounts[itemStatus] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
@@ -932,7 +574,7 @@ namespace SabreTools.DatFiles
|
|||||||
ConcurrentList<DatItem> output = [];
|
ConcurrentList<DatItem> output = [];
|
||||||
|
|
||||||
// Check for an empty rom list first
|
// Check for an empty rom list first
|
||||||
if (TotalCount == 0)
|
if (DatStatistics.TotalCount == 0)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
// We want to get the proper key for the DatItem
|
// We want to get the proper key for the DatItem
|
||||||
@@ -982,7 +624,7 @@ namespace SabreTools.DatFiles
|
|||||||
public bool HasDuplicates(DatItem datItem, bool sorted = false)
|
public bool HasDuplicates(DatItem datItem, bool sorted = false)
|
||||||
{
|
{
|
||||||
// Check for an empty rom list first
|
// Check for an empty rom list first
|
||||||
if (TotalCount == 0)
|
if (DatStatistics.TotalCount == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We want to get the proper key for the DatItem
|
// We want to get the proper key for the DatItem
|
||||||
@@ -1003,7 +645,7 @@ namespace SabreTools.DatFiles
|
|||||||
public void RecalculateStats()
|
public void RecalculateStats()
|
||||||
{
|
{
|
||||||
// Wipe out any stats already there
|
// Wipe out any stats already there
|
||||||
ResetStatistics();
|
DatStatistics.ResetStatistics();
|
||||||
|
|
||||||
// If we have a blank Dat in any way, return
|
// If we have a blank Dat in any way, return
|
||||||
if (items == null)
|
if (items == null)
|
||||||
@@ -1018,54 +660,40 @@ namespace SabreTools.DatFiles
|
|||||||
|
|
||||||
foreach (DatItem item in datItems)
|
foreach (DatItem item in datItems)
|
||||||
{
|
{
|
||||||
AddItemStatistics(item);
|
DatStatistics.AddItemStatistics(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reset all statistics
|
|
||||||
/// </summary>
|
|
||||||
public void ResetStatistics()
|
|
||||||
{
|
|
||||||
TotalCount = 0;
|
|
||||||
ItemCounts = [];
|
|
||||||
GameCount = 0;
|
|
||||||
TotalSize = 0;
|
|
||||||
HashCounts = [];
|
|
||||||
StatusCounts = [];
|
|
||||||
RemovedCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the highest-order Field value that represents the statistics
|
/// Get the highest-order Field value that represents the statistics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ItemKey GetBestAvailable()
|
private ItemKey GetBestAvailable()
|
||||||
{
|
{
|
||||||
// Get the required counts
|
// Get the required counts
|
||||||
long diskCount = GetItemCount(ItemType.Disk);
|
long diskCount = DatStatistics.GetItemCount(ItemType.Disk);
|
||||||
long mediaCount = GetItemCount(ItemType.Media);
|
long mediaCount = DatStatistics.GetItemCount(ItemType.Media);
|
||||||
long romCount = GetItemCount(ItemType.Rom);
|
long romCount = DatStatistics.GetItemCount(ItemType.Rom);
|
||||||
long nodumpCount = GetStatusCount(ItemStatus.Nodump);
|
long nodumpCount = DatStatistics.GetStatusCount(ItemStatus.Nodump);
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-512, we bucket by that
|
// If all items are supposed to have a SHA-512, we bucket by that
|
||||||
if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA512))
|
if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA512))
|
||||||
return ItemKey.SHA512;
|
return ItemKey.SHA512;
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-384, we bucket by that
|
// If all items are supposed to have a SHA-384, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA384))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA384))
|
||||||
return ItemKey.SHA384;
|
return ItemKey.SHA384;
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-256, we bucket by that
|
// If all items are supposed to have a SHA-256, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA256))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA256))
|
||||||
return ItemKey.SHA256;
|
return ItemKey.SHA256;
|
||||||
|
|
||||||
// If all items are supposed to have a SHA-1, we bucket by that
|
// If all items are supposed to have a SHA-1, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.SHA1))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.SHA1))
|
||||||
return ItemKey.SHA1;
|
return ItemKey.SHA1;
|
||||||
|
|
||||||
// If all items are supposed to have a MD5, we bucket by that
|
// If all items are supposed to have a MD5, we bucket by that
|
||||||
else if (diskCount + mediaCount + romCount - nodumpCount == GetHashCount(HashType.MD5))
|
else if (diskCount + mediaCount + romCount - nodumpCount == DatStatistics.GetHashCount(HashType.MD5))
|
||||||
return ItemKey.MD5;
|
return ItemKey.MD5;
|
||||||
|
|
||||||
// Otherwise, we bucket by CRC
|
// Otherwise, we bucket by CRC
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace SabreTools.DatTools
|
|||||||
#region Perform setup
|
#region Perform setup
|
||||||
|
|
||||||
// If the DAT is not populated and inverse is not set, inform the user and quit
|
// If the DAT is not populated and inverse is not set, inform the user and quit
|
||||||
if (datFile.Items.TotalCount == 0 && !inverse)
|
if (datFile.Items.DatStatistics.TotalCount == 0 && !inverse)
|
||||||
{
|
{
|
||||||
logger.User("No entries were found to rebuild, exiting...");
|
logger.User("No entries were found to rebuild, exiting...");
|
||||||
return false;
|
return false;
|
||||||
@@ -205,7 +205,7 @@ namespace SabreTools.DatTools
|
|||||||
#region Perform setup
|
#region Perform setup
|
||||||
|
|
||||||
// If the DAT is not populated and inverse is not set, inform the user and quit
|
// If the DAT is not populated and inverse is not set, inform the user and quit
|
||||||
if (datFile.Items.TotalCount == 0 && !inverse)
|
if (datFile.Items.DatStatistics.TotalCount == 0 && !inverse)
|
||||||
{
|
{
|
||||||
logger.User("No entries were found to rebuild, exiting...");
|
logger.User("No entries were found to rebuild, exiting...");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace SabreTools.DatTools
|
|||||||
public static (DatFile? extADat, DatFile? extBDat) SplitByExtension(DatFile datFile, List<string> extA, List<string> extB)
|
public static (DatFile? extADat, DatFile? extBDat) SplitByExtension(DatFile datFile, List<string> extA, List<string> extB)
|
||||||
{
|
{
|
||||||
// If roms is empty, return false
|
// If roms is empty, return false
|
||||||
if (datFile.Items.TotalCount == 0)
|
if (datFile.Items.DatStatistics.TotalCount == 0)
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|
||||||
InternalStopwatch watch = new($"Splitting DAT by extension");
|
InternalStopwatch watch = new($"Splitting DAT by extension");
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices.ComTypes;
|
||||||
|
|
||||||
#if NET40_OR_GREATER || NETCOREAPP
|
#if NET40_OR_GREATER || NETCOREAPP
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
#endif
|
#endif
|
||||||
@@ -50,7 +52,6 @@ namespace SabreTools.DatTools
|
|||||||
// Init total
|
// Init total
|
||||||
DatStatistics totalStats = new()
|
DatStatistics totalStats = new()
|
||||||
{
|
{
|
||||||
Statistics = [],
|
|
||||||
DisplayName = "DIR: All DATs",
|
DisplayName = "DIR: All DATs",
|
||||||
MachineCount = 0,
|
MachineCount = 0,
|
||||||
IsDirectory = true,
|
IsDirectory = true,
|
||||||
@@ -60,7 +61,6 @@ namespace SabreTools.DatTools
|
|||||||
string? lastdir = null;
|
string? lastdir = null;
|
||||||
DatStatistics dirStats = new()
|
DatStatistics dirStats = new()
|
||||||
{
|
{
|
||||||
Statistics = [],
|
|
||||||
MachineCount = 0,
|
MachineCount = 0,
|
||||||
IsDirectory = true,
|
IsDirectory = true,
|
||||||
};
|
};
|
||||||
@@ -79,11 +79,10 @@ namespace SabreTools.DatTools
|
|||||||
#else
|
#else
|
||||||
dirStats.DisplayName = $"DIR: {WebUtility.HtmlEncode(lastdir)}";
|
dirStats.DisplayName = $"DIR: {WebUtility.HtmlEncode(lastdir)}";
|
||||||
#endif
|
#endif
|
||||||
dirStats.MachineCount = dirStats.Statistics.GameCount;
|
dirStats.MachineCount = dirStats.GameCount;
|
||||||
stats.Add(dirStats);
|
stats.Add(dirStats);
|
||||||
dirStats = new DatStatistics
|
dirStats = new DatStatistics
|
||||||
{
|
{
|
||||||
Statistics = [],
|
|
||||||
MachineCount = 0,
|
MachineCount = 0,
|
||||||
IsDirectory = true,
|
IsDirectory = true,
|
||||||
};
|
};
|
||||||
@@ -97,23 +96,20 @@ namespace SabreTools.DatTools
|
|||||||
// Add single DAT stats (if asked)
|
// Add single DAT stats (if asked)
|
||||||
if (single)
|
if (single)
|
||||||
{
|
{
|
||||||
DatStatistics individualStats = new()
|
DatStatistics individualStats = datdata.Items.DatStatistics;
|
||||||
{
|
individualStats.DisplayName = datdata.Header.GetStringFieldValue(DatHeader.FileNameKey);
|
||||||
Statistics = datdata.Items,
|
individualStats.MachineCount = datdata.Items.Keys.Count;
|
||||||
DisplayName = datdata.Header.GetStringFieldValue(DatHeader.FileNameKey),
|
individualStats.IsDirectory = false;
|
||||||
MachineCount = datdata.Items.Keys.Count,
|
|
||||||
IsDirectory = false,
|
|
||||||
};
|
|
||||||
stats.Add(individualStats);
|
stats.Add(individualStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add single DAT stats to dir
|
// Add single DAT stats to dir
|
||||||
dirStats.Statistics.AddStatistics(datdata.Items);
|
dirStats.AddStatistics(datdata.Items.DatStatistics);
|
||||||
dirStats.Statistics.GameCount += datdata.Items.Keys.Count;
|
dirStats.GameCount += datdata.Items.Keys.Count;
|
||||||
|
|
||||||
// Add single DAT stats to totals
|
// Add single DAT stats to totals
|
||||||
totalStats.Statistics.AddStatistics(datdata.Items);
|
totalStats.AddStatistics(datdata.Items.DatStatistics);
|
||||||
totalStats.Statistics.GameCount += datdata.Items.Keys.Count;
|
totalStats.GameCount += datdata.Items.Keys.Count;
|
||||||
|
|
||||||
// Make sure to assign the new directory
|
// Make sure to assign the new directory
|
||||||
lastdir = thisdir;
|
lastdir = thisdir;
|
||||||
@@ -129,12 +125,12 @@ namespace SabreTools.DatTools
|
|||||||
#else
|
#else
|
||||||
dirStats.DisplayName = $"DIR: {WebUtility.HtmlEncode(lastdir)}";
|
dirStats.DisplayName = $"DIR: {WebUtility.HtmlEncode(lastdir)}";
|
||||||
#endif
|
#endif
|
||||||
dirStats.MachineCount = dirStats.Statistics.GameCount;
|
dirStats.MachineCount = dirStats.GameCount;
|
||||||
stats.Add(dirStats);
|
stats.Add(dirStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add total DAT stats
|
// Add total DAT stats
|
||||||
totalStats.MachineCount = totalStats.Statistics.GameCount;
|
totalStats.MachineCount = totalStats.GameCount;
|
||||||
stats.Add(totalStats);
|
stats.Add(totalStats);
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace SabreTools.DatTools
|
|||||||
datFile.Items.BucketBy(ItemKey.Machine, DedupeType.None);
|
datFile.Items.BucketBy(ItemKey.Machine, DedupeType.None);
|
||||||
|
|
||||||
// Output the number of items we're going to be writing
|
// Output the number of items we're going to be writing
|
||||||
logger.User($"A total of {datFile.Items.TotalCount - datFile.Items.RemovedCount} items will be written out to '{datFile.Header.GetStringFieldValue(DatHeader.FileNameKey)}'");
|
logger.User($"A total of {datFile.Items.DatStatistics.TotalCount - datFile.Items.DatStatistics.RemovedCount} items will be written out to '{datFile.Header.GetStringFieldValue(DatHeader.FileNameKey)}'");
|
||||||
|
|
||||||
// Get the outfile names
|
// Get the outfile names
|
||||||
Dictionary<DatFormat, string> outfiles = datFile.Header.CreateOutFileNames(outDir!, overwrite);
|
Dictionary<DatFormat, string> outfiles = datFile.Header.CreateOutFileNames(outDir!, overwrite);
|
||||||
@@ -121,24 +121,22 @@ namespace SabreTools.DatTools
|
|||||||
/// <param name="datFile">Current DatFile object to write from</param>
|
/// <param name="datFile">Current DatFile object to write from</param>
|
||||||
public static void WriteStatsToConsole(DatFile datFile)
|
public static void WriteStatsToConsole(DatFile datFile)
|
||||||
{
|
{
|
||||||
long diskCount = datFile.Items.GetItemCount(ItemType.Disk);
|
long diskCount = datFile.Items.DatStatistics.GetItemCount(ItemType.Disk);
|
||||||
long mediaCount = datFile.Items.GetItemCount(ItemType.Media);
|
long mediaCount = datFile.Items.DatStatistics.GetItemCount(ItemType.Media);
|
||||||
long romCount = datFile.Items.GetItemCount(ItemType.Rom);
|
long romCount = datFile.Items.DatStatistics.GetItemCount(ItemType.Rom);
|
||||||
|
|
||||||
if (diskCount + mediaCount + romCount == 0)
|
if (diskCount + mediaCount + romCount == 0)
|
||||||
datFile.Items.RecalculateStats();
|
datFile.Items.RecalculateStats();
|
||||||
|
|
||||||
datFile.Items.BucketBy(ItemKey.Machine, DedupeType.None, norename: true);
|
datFile.Items.BucketBy(ItemKey.Machine, DedupeType.None, norename: true);
|
||||||
|
|
||||||
|
datFile.Items.DatStatistics.DisplayName = datFile.Header.GetStringFieldValue(DatHeader.FileNameKey);
|
||||||
|
datFile.Items.DatStatistics.MachineCount = datFile.Items.Keys.Count;
|
||||||
|
datFile.Items.DatStatistics.IsDirectory = false;
|
||||||
|
|
||||||
var statsList = new List<DatStatistics>
|
var statsList = new List<DatStatistics>
|
||||||
{
|
{
|
||||||
new()
|
datFile.Items.DatStatistics,
|
||||||
{
|
|
||||||
Statistics = datFile.Items,
|
|
||||||
DisplayName = datFile.Header.GetStringFieldValue(DatHeader.FileNameKey),
|
|
||||||
MachineCount = datFile.Items.Keys.Count,
|
|
||||||
IsDirectory = false,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
var consoleOutput = BaseReport.Create(StatReportFormat.None, statsList);
|
var consoleOutput = BaseReport.Create(StatReportFormat.None, statsList);
|
||||||
consoleOutput!.WriteToFile(null, true, true);
|
consoleOutput!.WriteToFile(null, true, true);
|
||||||
@@ -210,11 +208,11 @@ namespace SabreTools.DatTools
|
|||||||
datFile.Items.RecalculateStats();
|
datFile.Items.RecalculateStats();
|
||||||
|
|
||||||
// If there's nothing there, abort
|
// If there's nothing there, abort
|
||||||
if (datFile.Items.TotalCount == 0)
|
if (datFile.Items.DatStatistics.TotalCount == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If every item is removed, abort
|
// If every item is removed, abort
|
||||||
if (datFile.Items.TotalCount == datFile.Items.RemovedCount)
|
if (datFile.Items.DatStatistics.TotalCount == datFile.Items.DatStatistics.RemovedCount)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using SabreTools.DatFiles;
|
||||||
using SabreTools.Logging;
|
using SabreTools.Logging;
|
||||||
using SabreTools.Reports.Formats;
|
using SabreTools.Reports.Formats;
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
using SabreTools.DatFiles;
|
|
||||||
|
|
||||||
namespace SabreTools.Reports
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Statistics wrapper for outputting
|
|
||||||
/// </summary>
|
|
||||||
public class DatStatistics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// ItemDictionary representing the statistics
|
|
||||||
/// </summary>
|
|
||||||
public ItemDictionary? Statistics { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Name to display on output
|
|
||||||
/// </summary>
|
|
||||||
public string? DisplayName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Total machine count to use on output
|
|
||||||
/// </summary>
|
|
||||||
public long MachineCount { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if statistics are for a directory or not
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDirectory { get; set; } = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using SabreTools.DatFiles;
|
||||||
using SabreTools.DatItems;
|
using SabreTools.DatItems;
|
||||||
using SabreTools.Hashing;
|
using SabreTools.Hashing;
|
||||||
using SabreTools.Logging;
|
using SabreTools.Logging;
|
||||||
@@ -228,7 +229,7 @@ body {
|
|||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(GetBytesReadable(stat.Statistics!.TotalSize));
|
xtw.WriteString(GetBytesReadable(stat.TotalSize));
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
@@ -238,39 +239,39 @@ body {
|
|||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetItemCount(ItemType.Rom).ToString());
|
xtw.WriteString(stat.GetItemCount(ItemType.Rom).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetItemCount(ItemType.Disk).ToString());
|
xtw.WriteString(stat.GetItemCount(ItemType.Disk).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetHashCount(HashType.CRC32).ToString());
|
xtw.WriteString(stat.GetHashCount(HashType.CRC32).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetHashCount(HashType.MD5).ToString());
|
xtw.WriteString(stat.GetHashCount(HashType.MD5).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetHashCount(HashType.SHA1).ToString());
|
xtw.WriteString(stat.GetHashCount(HashType.SHA1).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetHashCount(HashType.SHA256).ToString());
|
xtw.WriteString(stat.GetHashCount(HashType.SHA256).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
|
|
||||||
if (baddumpCol)
|
if (baddumpCol)
|
||||||
{
|
{
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetStatusCount(ItemStatus.BadDump).ToString());
|
xtw.WriteString(stat.GetStatusCount(ItemStatus.BadDump).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +279,7 @@ body {
|
|||||||
{
|
{
|
||||||
xtw.WriteStartElement("td");
|
xtw.WriteStartElement("td");
|
||||||
xtw.WriteAttributeString("align", "right");
|
xtw.WriteAttributeString("align", "right");
|
||||||
xtw.WriteString(stat.Statistics.GetStatusCount(ItemStatus.Nodump).ToString());
|
xtw.WriteString(stat.GetStatusCount(ItemStatus.Nodump).ToString());
|
||||||
xtw.WriteEndElement(); // td
|
xtw.WriteEndElement(); // td
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using SabreTools.DatFiles;
|
||||||
using SabreTools.DatItems;
|
using SabreTools.DatItems;
|
||||||
using SabreTools.Hashing;
|
using SabreTools.Hashing;
|
||||||
using SabreTools.IO.Writers;
|
using SabreTools.IO.Writers;
|
||||||
@@ -130,18 +131,18 @@ namespace SabreTools.Reports.Formats
|
|||||||
string[] values =
|
string[] values =
|
||||||
[
|
[
|
||||||
stat.DisplayName!,
|
stat.DisplayName!,
|
||||||
stat.Statistics!.TotalSize.ToString(),
|
stat.TotalSize.ToString(),
|
||||||
stat.MachineCount.ToString(),
|
stat.MachineCount.ToString(),
|
||||||
stat.Statistics.GetItemCount(ItemType.Rom).ToString(),
|
stat.GetItemCount(ItemType.Rom).ToString(),
|
||||||
stat.Statistics.GetItemCount(ItemType.Disk).ToString(),
|
stat.GetItemCount(ItemType.Disk).ToString(),
|
||||||
stat.Statistics.GetHashCount(HashType.CRC32).ToString(),
|
stat.GetHashCount(HashType.CRC32).ToString(),
|
||||||
stat.Statistics.GetHashCount(HashType.MD5).ToString(),
|
stat.GetHashCount(HashType.MD5).ToString(),
|
||||||
stat.Statistics.GetHashCount(HashType.SHA1).ToString(),
|
stat.GetHashCount(HashType.SHA1).ToString(),
|
||||||
stat.Statistics.GetHashCount(HashType.SHA256).ToString(),
|
stat.GetHashCount(HashType.SHA256).ToString(),
|
||||||
stat.Statistics.GetHashCount(HashType.SHA384).ToString(),
|
stat.GetHashCount(HashType.SHA384).ToString(),
|
||||||
stat.Statistics.GetHashCount(HashType.SHA512).ToString(),
|
stat.GetHashCount(HashType.SHA512).ToString(),
|
||||||
baddumpCol ? stat.Statistics.GetStatusCount(ItemStatus.BadDump).ToString() : string.Empty,
|
baddumpCol ? stat.GetStatusCount(ItemStatus.BadDump).ToString() : string.Empty,
|
||||||
nodumpCol ? stat.Statistics.GetStatusCount(ItemStatus.Nodump).ToString() : string.Empty,
|
nodumpCol ? stat.GetStatusCount(ItemStatus.Nodump).ToString() : string.Empty,
|
||||||
];
|
];
|
||||||
svw.WriteValues(values);
|
svw.WriteValues(values);
|
||||||
svw.Flush();
|
svw.Flush();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using SabreTools.DatFiles;
|
||||||
using SabreTools.DatItems;
|
using SabreTools.DatItems;
|
||||||
using SabreTools.Hashing;
|
using SabreTools.Hashing;
|
||||||
using SabreTools.Logging;
|
using SabreTools.Logging;
|
||||||
@@ -92,22 +93,22 @@ namespace SabreTools.Reports.Formats
|
|||||||
{
|
{
|
||||||
string line = @"'" + stat.DisplayName + @"':
|
string line = @"'" + stat.DisplayName + @"':
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
Uncompressed size: " + GetBytesReadable(stat.Statistics!.TotalSize) + @"
|
Uncompressed size: " + GetBytesReadable(stat!.TotalSize) + @"
|
||||||
Games found: " + stat.MachineCount + @"
|
Games found: " + stat.MachineCount + @"
|
||||||
Roms found: " + stat.Statistics.GetItemCount(ItemType.Rom) + @"
|
Roms found: " + stat.GetItemCount(ItemType.Rom) + @"
|
||||||
Disks found: " + stat.Statistics.GetItemCount(ItemType.Disk) + @"
|
Disks found: " + stat.GetItemCount(ItemType.Disk) + @"
|
||||||
Roms with CRC: " + stat.Statistics.GetHashCount(HashType.CRC32) + @"
|
Roms with CRC: " + stat.GetHashCount(HashType.CRC32) + @"
|
||||||
Roms with MD5: " + stat.Statistics.GetHashCount(HashType.MD5) + @"
|
Roms with MD5: " + stat.GetHashCount(HashType.MD5) + @"
|
||||||
Roms with SHA-1: " + stat.Statistics.GetHashCount(HashType.SHA1) + @"
|
Roms with SHA-1: " + stat.GetHashCount(HashType.SHA1) + @"
|
||||||
Roms with SHA-256: " + stat.Statistics.GetHashCount(HashType.SHA256) + @"
|
Roms with SHA-256: " + stat.GetHashCount(HashType.SHA256) + @"
|
||||||
Roms with SHA-384: " + stat.Statistics.GetHashCount(HashType.SHA384) + @"
|
Roms with SHA-384: " + stat.GetHashCount(HashType.SHA384) + @"
|
||||||
Roms with SHA-512: " + stat.Statistics.GetHashCount(HashType.SHA512) + "\n";
|
Roms with SHA-512: " + stat.GetHashCount(HashType.SHA512) + "\n";
|
||||||
|
|
||||||
if (baddumpCol)
|
if (baddumpCol)
|
||||||
line += " Roms with BadDump status: " + stat.Statistics.GetStatusCount(ItemStatus.BadDump) + "\n";
|
line += " Roms with BadDump status: " + stat.GetStatusCount(ItemStatus.BadDump) + "\n";
|
||||||
|
|
||||||
if (nodumpCol)
|
if (nodumpCol)
|
||||||
line += " Roms with Nodump status: " + stat.Statistics.GetStatusCount(ItemStatus.Nodump) + "\n";
|
line += " Roms with Nodump status: " + stat.GetStatusCount(ItemStatus.Nodump) + "\n";
|
||||||
|
|
||||||
// For spacing between DATs
|
// For spacing between DATs
|
||||||
line += "\n\n";
|
line += "\n\n";
|
||||||
|
|||||||
@@ -189,9 +189,10 @@ namespace SabreTools.Test.DatFiles
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void ResetStatisticsTest()
|
public void ResetStatisticsTest()
|
||||||
{
|
{
|
||||||
var dict = new ItemDictionary { GameCount = 1 };
|
var dict = new ItemDictionary();
|
||||||
dict.ResetStatistics();
|
dict.DatStatistics.GameCount = 1;
|
||||||
Assert.Equal(0, dict.GameCount);
|
dict.DatStatistics.ResetStatistics();
|
||||||
|
Assert.Equal(0, dict.DatStatistics.GameCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ namespace SabreTools.Test.DatTools
|
|||||||
|
|
||||||
var datFile = SabreTools.DatTools.Parser.CreateAndParse(filename, throwOnError: true);
|
var datFile = SabreTools.DatTools.Parser.CreateAndParse(filename, throwOnError: true);
|
||||||
Assert.Equal(datFormat, datFile.Header.GetFieldValue<DatFormat>(DatHeader.DatFormatKey));
|
Assert.Equal(datFormat, datFile.Header.GetFieldValue<DatFormat>(DatHeader.DatFormatKey));
|
||||||
Assert.Equal(totalCount, datFile.Items.TotalCount);
|
Assert.Equal(totalCount, datFile.Items.DatStatistics.TotalCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user