Add per-machine filtering to Batch

This commit is contained in:
Matt Nadareski
2020-09-04 20:57:30 -07:00
parent e2d0dc26b9
commit 4146972afe
4 changed files with 38 additions and 14 deletions

View File

@@ -821,13 +821,18 @@ namespace SabreTools.Library.DatFiles
/// Apply a Filter on the DatFile /// Apply a Filter on the DatFile
/// </summary> /// </summary>
/// <param name="filter">Filter to use</param> /// <param name="filter">Filter to use</param>
/// <param name="perMachine">True if entire machines are considered, false otherwise (default)</param>
/// <returns>True if the DatFile was filtered, false on error</returns> /// <returns>True if the DatFile was filtered, false on error</returns>
public bool ApplyFilter(Filter filter) public bool ApplyFilter(Filter filter, bool perMachine = false)
{ {
// If we have a null filter, return false // If we have a null filter, return false
if (filter == null) if (filter == null)
return false; return false;
// If we're filtering per machine, bucket by machine first
if (perMachine)
Items.BucketBy(Field.Machine_Name, DedupeType.None);
try try
{ {
// Loop over every key in the dictionary // Loop over every key in the dictionary
@@ -835,6 +840,7 @@ namespace SabreTools.Library.DatFiles
foreach (string key in keys) foreach (string key in keys)
{ {
// For every item in the current key // For every item in the current key
bool machinePass = true;
List<DatItem> items = Items[key]; List<DatItem> items = Items[key];
foreach (DatItem item in items) foreach (DatItem item in items)
{ {
@@ -844,7 +850,25 @@ namespace SabreTools.Library.DatFiles
// If the rom doesn't pass the filter, mark for removal // If the rom doesn't pass the filter, mark for removal
if (!item.PassesFilter(filter)) if (!item.PassesFilter(filter))
{
item.Remove = true; item.Remove = true;
// If we're in machine mode, set and break
if (perMachine)
{
machinePass = false;
break;
}
}
}
// If we didn't pass and we're in machine mode, set all items as remove
if (perMachine && !machinePass)
{
foreach (DatItem item in items)
{
item.Remove = true;
}
} }
// Assign back for caution // Assign back for caution

View File

@@ -513,14 +513,6 @@ namespace SabreTools.Library.DatItems
#endregion #endregion
// TODO: Can there be a special filter for machine that says if one item in a machine
// explicitly passes then the machine is included? This will be difficult to attempt to
// implement because technically, you'd want to keep games that don't match a negative
// instead of the inverse. Possible way of doing it would be: filter on machine-level
// things first, then see if any items inside explicitly fail. If ANY fail inside, filter
// out the machine. This would likely have to be an entirely separate flag. A proof
// of concept implementation would be best first, likely living under Filtering of
// the DatFile class.
#region Filtering #region Filtering
/// <summary> /// <summary>

View File

@@ -186,7 +186,7 @@ Options:
Set a header field (if default): set(header.field, value); Set a header field (if default): set(header.field, value);
Parse new file(s): input(datpath, ...); Parse new file(s): input(datpath, ...);
Perform a dir2dat: d2d(path, ...); Perform a dir2dat: d2d(path, ...);
Filter on a field and value: filter(machine.field|item.field, value, [negate = false]); Filter on a field and value: filter(machine.field|item.field, value, [negate = false, [perMachine = false]]);
Apply a MAME Extra INI for a field: extra(field, inipath); Apply a MAME Extra INI for a field: extra(field, inipath);
Perform a split/merge: merge(split|merged|nonmerged|full|device); Perform a split/merge: merge(split|merged|nonmerged|full|device);
Set game names from description: descname(); Set game names from description: descname();

View File

@@ -160,10 +160,10 @@ Reset the internal state: reset();";
// Apply a filter // Apply a filter
case "filter": case "filter":
if (command.Arguments.Count < 2 || command.Arguments.Count > 3) if (command.Arguments.Count < 2 || command.Arguments.Count > 4)
{ {
Globals.Logger.User($"Invoked {command.Name} and expected between 2-3 arguments, but {command.Arguments.Count} arguments were provided"); Globals.Logger.User($"Invoked {command.Name} and expected between 2-4 arguments, but {command.Arguments.Count} arguments were provided");
Globals.Logger.User("Usage: filter(field, value, [negate = false]);"); Globals.Logger.User("Usage: filter(field, value, [negate = false, [perMachine = false]]);");
continue; continue;
} }
@@ -173,6 +173,9 @@ Reset the internal state: reset();";
bool? filterNegate = false; bool? filterNegate = false;
if (command.Arguments.Count == 3) if (command.Arguments.Count == 3)
filterNegate = command.Arguments[2].AsYesNo(); filterNegate = command.Arguments[2].AsYesNo();
bool? filterPerMachine = false;
if (command.Arguments.Count == 4)
filterPerMachine = command.Arguments[3].AsYesNo();
// If we had an invalid input, log and continue // If we had an invalid input, log and continue
if (filterField == Field.NULL) if (filterField == Field.NULL)
@@ -185,13 +188,18 @@ Reset the internal state: reset();";
Globals.Logger.User($"{command.Arguments[2]} was an invalid true/false value"); Globals.Logger.User($"{command.Arguments[2]} was an invalid true/false value");
continue; continue;
} }
if (filterPerMachine == null)
{
Globals.Logger.User($"{command.Arguments[3]} was an invalid true/false value");
continue;
}
// Create a filter with this new set of fields // Create a filter with this new set of fields
Filter filter = new Filter(); Filter filter = new Filter();
filter.SetFilter(filterField, filterValue, filterNegate.Value); filter.SetFilter(filterField, filterValue, filterNegate.Value);
// Apply the filter blindly // Apply the filter blindly
datFile.ApplyFilter(filter); datFile.ApplyFilter(filter, filterPerMachine.Value);
datFile.Items.ClearMarked(); // TODO: We might not want to remove immediately datFile.Items.ClearMarked(); // TODO: We might not want to remove immediately
break; break;