Checkpoint reflection replacement

This commit is contained in:
Matt Nadareski
2026-04-07 09:12:27 -04:00
parent 39a31b3a97
commit b4be581879
4 changed files with 284 additions and 14 deletions

View File

@@ -336,6 +336,7 @@ namespace SabreTools.Metadata.DatFiles.Test
System = "system",
Tags = "tags",
TitleID = "titleid",
Url = "url",
Video = [CreateMetadataVideo()],
Year = "year",
};
@@ -1113,6 +1114,7 @@ namespace SabreTools.Metadata.DatFiles.Test
Assert.Equal("system", machine.System);
Assert.Equal("tags", machine.Tags);
Assert.Equal("titleid", machine.TitleID);
Assert.Equal("url", machine.Url);
Assert.Equal("year", machine.Year);
string[]? categories = machine.Category;

View File

@@ -1,5 +1,6 @@
using System;
using SabreTools.Data.Models.Metadata;
using SabreTools.Hashing;
using Xunit;
namespace SabreTools.Metadata.Filter.Test
@@ -1218,5 +1219,192 @@ namespace SabreTools.Metadata.Filter.Test
}
#endregion
#region Input
[Theory]
[InlineData("input.buttons", "12345")]
[InlineData("input.coins", "12345")]
[InlineData("input.control", "control")]
[InlineData("input.controlattr", "control")]
[InlineData("input.players", "12345")]
[InlineData("input.service", "yes")]
[InlineData("input.tilt", "yes")]
public void Matches_Input(string itemField, string value)
{
var filter = new FilterObject(itemField, value, Operation.Equals);
Input obj = new Input
{
Buttons = 12345,
Coins = 12345,
ControlAttr = "control",
Players = 12345,
Service = true,
Tilt = true,
};
bool actual = filter.Matches(obj);
Assert.True(actual);
}
#endregion
#region Instance
[Theory]
[InlineData("instance.name", "name")]
public void Matches_Instance(string itemField, string value)
{
var filter = new FilterObject(itemField, value, Operation.Equals);
Instance obj = new Instance
{
Name = "name",
};
bool actual = filter.Matches(obj);
Assert.True(actual);
}
#endregion
#region Machine
[Theory]
[InlineData("machine.board", "board")]
[InlineData("machine.buttons", "buttons")]
[InlineData("machine.category", "category")]
[InlineData("machine.cloneof", "cloneof")]
[InlineData("machine.comment", "comment")]
[InlineData("machine.company", "company")]
[InlineData("machine.control", "control")]
[InlineData("machine.crc", "crc")]
[InlineData("machine.country", "country")]
[InlineData("machine.description", "description")]
[InlineData("machine.developer", "developer")]
[InlineData("machine.dirname", "dirname")]
[InlineData("machine.displaycount", "displaycount")]
[InlineData("machine.displaytype", "displaytype")]
[InlineData("machine.duplicateid", "duplicateid")]
[InlineData("machine.emulator", "emulator")]
[InlineData("machine.enabled", "enabled")]
[InlineData("machine.extra", "extra")]
[InlineData("machine.favorite", "favorite")]
[InlineData("machine.genmsxid", "genmsxid")]
[InlineData("machine.genre", "genre")]
[InlineData("machine.hash", "hash")]
[InlineData("machine.history", "history")]
[InlineData("machine.id", "id")]
[InlineData("machine.im1crc", "00000000")]
[InlineData("machine.im2crc", "00000000")]
[InlineData("machine.imagenumber", "imagenumber")]
[InlineData("machine.isbios", "yes")]
[InlineData("machine.isdevice", "yes")]
[InlineData("machine.ismechanical", "yes")]
[InlineData("machine.language", "language")]
[InlineData("machine.location", "location")]
[InlineData("machine.manufacturer", "manufacturer")]
[InlineData("machine.name", "name")]
[InlineData("machine.notes", "notes")]
[InlineData("machine.playedcount", "playedcount")]
[InlineData("machine.playedtime", "playedtime")]
[InlineData("machine.players", "players")]
[InlineData("machine.publisher", "publisher")]
[InlineData("machine.ratings", "ratings")]
[InlineData("machine.rebuildto", "rebuildto")]
[InlineData("machine.relatedto", "relatedto")]
[InlineData("machine.releasenumber", "releasenumber")]
[InlineData("machine.romof", "romof")]
[InlineData("machine.rotation", "rotation")]
[InlineData("machine.runnable", "yes")]
[InlineData("machine.sampleof", "sampleof")]
[InlineData("machine.savetype", "savetype")]
[InlineData("machine.score", "score")]
[InlineData("machine.source", "source")]
[InlineData("machine.sourcefile", "sourcefile")]
[InlineData("machine.sourcerom", "sourcerom")]
[InlineData("machine.status", "status")]
[InlineData("machine.subgenre", "subgenre")]
[InlineData("machine.supported", "yes")]
[InlineData("machine.system", "system")]
[InlineData("machine.tags", "tags")]
[InlineData("machine.type", "bios")]
[InlineData("machine.type", "device")]
[InlineData("machine.type", "mechanical")]
[InlineData("machine.titleid", "titleid")]
[InlineData("machine.url", "url")]
[InlineData("machine.year", "year")]
public void Matches_Machine(string itemField, string value)
{
var filter = new FilterObject(itemField, value, Operation.Equals);
Machine obj = new Machine
{
Board = "board",
Buttons = "buttons",
Category = ["category"],
CloneOf = "cloneof",
CloneOfId = "cloneofid",
Comment = ["comment"],
Company = "company",
Control = "control",
CRC = "crc",
Country = "country",
Description = "description",
Developer = "developer",
DirName = "dirname",
DisplayCount = "displaycount",
DisplayType = "displaytype",
DuplicateID = "duplicateid",
Emulator = "emulator",
Enabled = "enabled",
Extra = "extra",
Favorite = "favorite",
GenMSXID = "genmsxid",
Genre = "genre",
Hash = "hash",
History = "history",
Id = "id",
Im1CRC = HashType.CRC32.ZeroString,
Im2CRC = HashType.CRC32.ZeroString,
ImageNumber = "imagenumber",
IsBios = true,
IsDevice = true,
IsMechanical = true,
Language = "language",
Location = "location",
Manufacturer = "manufacturer",
Name = "name",
Notes = "notes",
PlayedCount = "playedcount",
PlayedTime = "playedtime",
Players = "players",
Publisher = "publisher",
Ratings = "ratings",
RebuildTo = "rebuildto",
RelatedTo = "relatedto",
ReleaseNumber = "releasenumber",
RomOf = "romof",
Rotation = "rotation",
Runnable = Runnable.Yes,
SampleOf = "sampleof",
SaveType = "savetype",
Score = "score",
Source = "source",
SourceFile = "sourcefile",
SourceRom = "sourcerom",
Status = "status",
Subgenre = "subgenre",
Supported = Supported.Yes,
System = "system",
Tags = "tags",
TitleID = "titleid",
Url = "url",
Year = "year",
};
bool actual = filter.Matches(obj);
Assert.True(actual);
}
#endregion
}
}

View File

@@ -388,6 +388,96 @@ namespace SabreTools.Metadata.Filter
"value",
];
/// <summary>
/// Known keys for Input
/// </summary>
private static readonly string[] _inputKeys =
[
"buttons",
"coins",
"control",
"controlattr",
"players",
"service",
"tilt",
];
/// <summary>
/// Known keys for Instance
/// </summary>
private static readonly string[] _instanceKeys =
[
"name",
];
/// <summary>
/// Known keys for Machine
/// </summary>
private static readonly string[] _machineKeys =
[
"board",
"buttons",
"category",
"cloneof",
"comment",
"company",
"control",
"crc",
"country",
"description",
"developer",
"dirname",
"displaycount",
"displaytype",
"duplicateid",
"emulator",
"enabled",
"extra",
"favorite",
"genmsxid",
"genre",
"hash",
"history",
"id",
"im1crc",
"im2crc",
"imagenumber",
"isbios",
"isdevice",
"ismechanical",
"language",
"location",
"manufacturer",
"name",
"notes",
"playedcount",
"playedtime",
"players",
"publisher",
"ratings",
"rebuildto",
"relatedto",
"releasenumber",
"romof",
"rotation",
"runnable",
"sampleof",
"savetype",
"score",
"source",
"sourcefile",
"sourcerom",
"status",
"subgenre",
"supported",
"system",
"tags",
"titleid",
"type",
"url",
"year",
];
#endregion
/// <summary>
@@ -490,22 +580,9 @@ namespace SabreTools.Metadata.Filter
/// </summary>
private static bool ParseMachineFilterId(ref string itemName, ref string fieldName)
{
// Special case for machine type
if (string.Equals(fieldName, "type", StringComparison.OrdinalIgnoreCase))
{
itemName = "machine";
fieldName = "type";
return true;
}
// Get the set of properties
var properties = GetProperties(typeof(Machine));
if (properties is null)
return false;
// Get if there's a match to a property
string localFieldName = fieldName;
string? propertyMatch = Array.Find(properties, c => string.Equals(c, localFieldName, StringComparison.OrdinalIgnoreCase));
string? propertyMatch = Array.Find(_machineKeys, c => string.Equals(c, localFieldName, StringComparison.OrdinalIgnoreCase));
if (propertyMatch is null)
return false;
@@ -600,6 +677,8 @@ namespace SabreTools.Metadata.Filter
"extension" => _extensionKeys,
"feature" or "partfeature" => _featureKeys,
"info" => _infoKeys,
"input" => _inputKeys,
"instance" => _instanceKeys,
_ => null,
};

View File

@@ -1348,6 +1348,7 @@ namespace SabreTools.Metadata.Filter
case "coins":
checkValue = obj.Coins?.ToString();
return true;
case "control":
case "controlattr":
checkValue = obj.ControlAttr;
return true;