Hard split region and quarantine

This commit is contained in:
Matt Nadareski
2026-07-04 23:58:29 -04:00
parent 2aff801f1f
commit a2c9cb6a71
9 changed files with 589 additions and 477 deletions

View File

@@ -2717,39 +2717,6 @@ namespace SabreTools.RedumpLib.Test.Data
#region Region
/// <summary>
/// Region values that don't have redump.info shortnames
/// </summary>
private static readonly Region?[] _regionsWithoutInfoShortname =
[
Region.AsiaEurope,
Region.AsiaUSA,
Region.AustraliaGermany,
Region.AustraliaNewZealand,
Region.AustriaSwitzerland,
Region.BelgiumNetherlands,
Region.EuropeAsia,
Region.EuropeAustralia,
Region.EuropeCanada,
Region.EuropeGermany,
Region.FranceSpain,
Region.GreaterChina,
Region.JapanAsia,
Region.JapanEurope,
Region.JapanKorea,
Region.JapanUSA,
Region.SpainPortugal,
Region.UKAustralia,
Region.USAAsia,
Region.USAAustralia,
Region.USABrazil,
Region.USACanada,
Region.USAEurope,
Region.USAGermany,
Region.USAJapan,
Region.USAKorea,
];
/// <summary>
/// Check that every Region has a long name provided
/// </summary>
@@ -2776,10 +2743,6 @@ namespace SabreTools.RedumpLib.Test.Data
[MemberData(nameof(GenerateRegionTestData))]
public void Region_ShortName(Region? region, bool expectNull)
{
// HACK: Hardcoded list of aggregate regions to ignore
if (_regionsWithoutInfoShortname.Contains(region))
expectNull = true;
var actual = region.ShortName();
if (expectNull)
@@ -2815,50 +2778,6 @@ namespace SabreTools.RedumpLib.Test.Data
Assert.Equal(totalCount, filteredRegions.Count);
}
/// <summary>
/// Check that every Region has a short name provided
/// </summary>
/// <param name="region">Region value to check</param>
/// <param name="expectNull">True to expect a null value, false otherwise</param>
[Theory]
[MemberData(nameof(GenerateRegionTestData))]
public void Region_ShortNameAlt(Region? region, bool expectNull)
{
var actual = region.ShortNameAlt();
if (expectNull)
Assert.Null(actual);
else
Assert.NotNull(actual);
}
/// <summary>
/// Ensure that every Region that has a short name that is unique
/// </summary>
[Fact]
public void Region_ShortNameAlt_NoDuplicates()
{
var fullRegions = Enum.GetValues<Region>().Cast<Region?>().ToList();
var filteredRegions = new Dictionary<string, Region?>();
int totalCount = 0;
foreach (Region? region in fullRegions)
{
var code = region.ShortNameAlt();
if (string.IsNullOrEmpty(code))
continue;
// Throw if the code already exists
if (filteredRegions.ContainsKey(code))
throw new DuplicateNameException($"Code {code} already in dictionary");
filteredRegions[code] = region;
totalCount++;
}
Assert.Equal(totalCount, filteredRegions.Count);
}
/// <summary>
/// Check that every Region can be mapped from a string
/// </summary>

View File

@@ -1,13 +0,0 @@
namespace SabreTools.RedumpLib.Attributes
{
/// <summary>
/// Attribute specifc to Region values
/// </summary>
public class RegionCodeAttribute : HumanReadableAttribute
{
/// <summary>
/// redump.org short code
/// </summary>
public string? RedumpOrgCode { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1973,7 +1973,7 @@ namespace SabreTools.RedumpLib.Data
/// <param name="region"></param>
/// <returns></returns>
public static string? LongName(this Region region)
=> (AttributeHelper<Region>.GetHumanReadableAttribute(region) as RegionCodeAttribute)?.LongName;
=> AttributeHelper<Region>.GetHumanReadableAttribute(region)?.LongName;
/// <summary>
/// Get the Redump longnames for each known region
@@ -1981,7 +1981,7 @@ namespace SabreTools.RedumpLib.Data
/// <param name="region"></param>
/// <returns></returns>
public static string? LongName(this Region? region)
=> (AttributeHelper<Region?>.GetHumanReadableAttribute(region) as RegionCodeAttribute)?.LongName;
=> AttributeHelper<Region?>.GetHumanReadableAttribute(region)?.LongName;
/// <summary>
/// Get the Redump shortnames for each known region
@@ -1989,7 +1989,7 @@ namespace SabreTools.RedumpLib.Data
/// <param name="region"></param>
/// <returns></returns>
public static string? ShortName(this Region region)
=> (AttributeHelper<Region>.GetHumanReadableAttribute(region) as RegionCodeAttribute)?.ShortName;
=> AttributeHelper<Region>.GetHumanReadableAttribute(region)?.ShortName;
/// <summary>
/// Get the Redump shortnames for each known region
@@ -1997,23 +1997,7 @@ namespace SabreTools.RedumpLib.Data
/// <param name="region"></param>
/// <returns></returns>
public static string? ShortName(this Region? region)
=> (AttributeHelper<Region?>.GetHumanReadableAttribute(region) as RegionCodeAttribute)?.ShortName;
/// <summary>
/// Get the Redump shortnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string? ShortNameAlt(this Region region)
=> (AttributeHelper<Region>.GetHumanReadableAttribute(region) as RegionCodeAttribute)?.RedumpOrgCode;
/// <summary>
/// Get the Redump shortnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string? ShortNameAlt(this Region? region)
=> (AttributeHelper<Region?>.GetHumanReadableAttribute(region) as RegionCodeAttribute)?.RedumpOrgCode;
=> AttributeHelper<Region?>.GetHumanReadableAttribute(region)?.ShortName;
/// <summary>
/// Get the Region enum value for a given string
@@ -2034,11 +2018,6 @@ namespace SabreTools.RedumpLib.Data
if (index > -1)
return redumpSystems[index];
// Check redump.org short names
index = Array.FindIndex(redumpSystems, s => region == s.ShortNameAlt()?.ToLowerInvariant());
if (index > -1)
return redumpSystems[index];
// Check long names
index = Array.FindIndex(redumpSystems, s => region == s.LongName()?.ToLowerInvariant()
|| region == s.LongName()?.Replace(" ", string.Empty)?.ToLowerInvariant());

View File

@@ -1,7 +1,6 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SabreTools.RedumpLib.Data;
namespace SabreTools.RedumpLib.RedumpOrg.Converters
{
@@ -28,7 +27,7 @@ namespace SabreTools.RedumpLib.RedumpOrg.Converters
public override void WriteJson(JsonWriter writer, Region? value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value.ShortNameAlt() ?? string.Empty);
JToken t = JToken.FromObject(value.ShortName() ?? string.Empty);
t.WriteTo(writer);
}
}

View File

@@ -1,5 +1,5 @@
using SabreTools.RedumpLib.RedumpOrg.Attributes;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.RedumpOrg.Attributes;
using HumanReadableAttribute = SabreTools.RedumpLib.Attributes.HumanReadableAttribute;
namespace SabreTools.RedumpLib.RedumpOrg
@@ -354,4 +354,250 @@ namespace SabreTools.RedumpLib.RedumpOrg
#endregion
}
/// <summary>
/// List of all regions defined in Redump.org
/// </summary>
/// <remarks>
/// https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
/// </remarks>
public enum Region
{
[HumanReadable(LongName = "Argentina", ShortName = "Ar")]
Argentina,
[HumanReadable(LongName = "Asia", ShortName = "A")]
Asia,
[HumanReadable(LongName = "Asia, Europe", ShortName = "A,E")]
AsiaEurope,
[HumanReadable(LongName = "Asia, USA", ShortName = "A,U")]
AsiaUSA,
[HumanReadable(LongName = "Australia", ShortName = "Au")]
Australia,
[HumanReadable(LongName = "Australia, Germany", ShortName = "Au,G")]
AustraliaGermany,
[HumanReadable(LongName = "Australia, New Zealand", ShortName = "Au,Nz")]
AustraliaNewZealand,
[HumanReadable(LongName = "Austria", ShortName = "At")]
Austria,
[HumanReadable(LongName = "Austria, Switzerland", ShortName = "At,Ch")]
AustriaSwitzerland,
[HumanReadable(LongName = "Belarus", ShortName = "By")]
Belarus,
[HumanReadable(LongName = "Belgium", ShortName = "Be")]
Belgium,
[HumanReadable(LongName = "Belgium, Netherlands", ShortName = "Be,N")]
BelgiumNetherlands,
[HumanReadable(LongName = "Brazil", ShortName = "B")]
Brazil,
[HumanReadable(LongName = "Bulgaria", ShortName = "Bg")]
Bulgaria,
[HumanReadable(LongName = "Canada", ShortName = "Ca")]
Canada,
[HumanReadable(LongName = "China", ShortName = "C")]
China,
[HumanReadable(LongName = "Croatia", ShortName = "Hr")]
Croatia,
[HumanReadable(LongName = "Czech", ShortName = "Cz")]
Czech,
[HumanReadable(LongName = "Denmark", ShortName = "Dk")]
Denmark,
[HumanReadable(LongName = "Estonia", ShortName = "Ee")]
Estonia,
[HumanReadable(LongName = "Europe", ShortName = "E")]
Europe,
[HumanReadable(LongName = "Europe, Asia", ShortName = "E,A")]
EuropeAsia,
[HumanReadable(LongName = "Europe, Australia", ShortName = "E,Au")]
EuropeAustralia,
[HumanReadable(LongName = "Europe, Canada", ShortName = "E,Ca")]
EuropeCanada,
[HumanReadable(LongName = "Europe, Germany", ShortName = "E,G")]
EuropeGermany,
[HumanReadable(LongName = "Export", ShortName = "Ex")]
Export,
[HumanReadable(LongName = "Finland", ShortName = "Fi")]
Finland,
[HumanReadable(LongName = "France", ShortName = "F")]
France,
[HumanReadable(LongName = "France, Spain", ShortName = "F,S")]
FranceSpain,
[HumanReadable(LongName = "Germany", ShortName = "G")]
Germany,
[HumanReadable(LongName = "Greater China", ShortName = "GC")]
GreaterChina,
[HumanReadable(LongName = "Greece", ShortName = "Gr")]
Greece,
[HumanReadable(LongName = "Hungary", ShortName = "H")]
Hungary,
[HumanReadable(LongName = "Iceland", ShortName = "Is")]
Iceland,
[HumanReadable(LongName = "India", ShortName = "In")]
India,
[HumanReadable(LongName = "Ireland", ShortName = "Ie")]
Ireland,
[HumanReadable(LongName = "Israel", ShortName = "Il")]
Israel,
[HumanReadable(LongName = "Italy", ShortName = "I")]
Italy,
[HumanReadable(LongName = "Japan", ShortName = "J")]
Japan,
[HumanReadable(LongName = "Japan, Asia", ShortName = "J,A")]
JapanAsia,
[HumanReadable(LongName = "Japan, Europe", ShortName = "J,E")]
JapanEurope,
[HumanReadable(LongName = "Japan, Korea", ShortName = "J,K")]
JapanKorea,
[HumanReadable(LongName = "Japan, USA", ShortName = "J,U")]
JapanUSA,
[HumanReadable(LongName = "Korea", ShortName = "K")]
Korea,
[HumanReadable(LongName = "Latin America", ShortName = "LAm")]
LatinAmerica,
[HumanReadable(LongName = "Lithuania", ShortName = "Lt")]
Lithuania,
[HumanReadable(LongName = "Netherlands", ShortName = "N")]
Netherlands,
[HumanReadable(LongName = "New Zealand", ShortName = "Nz")]
NewZealand,
[HumanReadable(LongName = "Norway", ShortName = "No")]
Norway,
[HumanReadable(LongName = "Poland", ShortName = "P")]
Poland,
[HumanReadable(LongName = "Portugal", ShortName = "Pt")]
Portugal,
[HumanReadable(LongName = "Romania", ShortName = "Ro")]
Romania,
[HumanReadable(LongName = "Russia", ShortName = "R")]
Russia,
[HumanReadable(LongName = "Scandinavia", ShortName = "Sca")]
Scandinavia,
[HumanReadable(LongName = "Serbia", ShortName = "Rs")]
Serbia,
[HumanReadable(LongName = "Singapore", ShortName = "Sg")]
Singapore,
[HumanReadable(LongName = "Slovakia", ShortName = "Sk")]
Slovakia,
[HumanReadable(LongName = "South Africa", ShortName = "Za")]
SouthAfrica,
[HumanReadable(LongName = "Spain", ShortName = "S")]
Spain,
[HumanReadable(LongName = "Spain, Portugal", ShortName = "S,Pt")]
SpainPortugal,
[HumanReadable(LongName = "Sweden", ShortName = "Sw")]
Sweden,
[HumanReadable(LongName = "Switzerland", ShortName = "Ch")]
Switzerland,
[HumanReadable(LongName = "Taiwan", ShortName = "Tw")]
Taiwan,
[HumanReadable(LongName = "Thailand", ShortName = "Th")]
Thailand,
[HumanReadable(LongName = "Turkey", ShortName = "Tr")]
Turkey,
[HumanReadable(LongName = "United Arab Emirates", ShortName = "Ae")]
UnitedArabEmirates,
[HumanReadable(LongName = "UK", ShortName = "Uk")]
UK,
[HumanReadable(LongName = "UK, Australia", ShortName = "Uk,Au")]
UKAustralia,
[HumanReadable(LongName = "Ukraine", ShortName = "Ua")]
Ukraine,
[HumanReadable(LongName = "USA", ShortName = "U")]
USA,
[HumanReadable(LongName = "USA, Asia", ShortName = "U,A")]
USAAsia,
[HumanReadable(LongName = "USA, Australia", ShortName = "U,Au")]
USAAustralia,
[HumanReadable(LongName = "USA, Brazil", ShortName = "U,B")]
USABrazil,
[HumanReadable(LongName = "USA, Canada", ShortName = "U,Ca")]
USACanada,
[HumanReadable(LongName = "USA, Europe", ShortName = "U,E")]
USAEurope,
[HumanReadable(LongName = "USA, Germany", ShortName = "U,G")]
USAGermany,
[HumanReadable(LongName = "USA, Japan", ShortName = "U,J")]
USAJapan,
[HumanReadable(LongName = "USA, Korea", ShortName = "U,K")]
USAKorea,
[HumanReadable(LongName = "World", ShortName = "W")]
World,
}
}

View File

@@ -411,5 +411,69 @@ namespace SabreTools.RedumpLib.RedumpOrg
}
#endregion
#region Region
/// <summary>
/// Get the Redump longnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string? LongName(this Region region)
=> AttributeHelper<Region>.GetHumanReadableAttribute(region)?.LongName;
/// <summary>
/// Get the Redump longnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string? LongName(this Region? region)
=> AttributeHelper<Region?>.GetHumanReadableAttribute(region)?.LongName;
/// <summary>
/// Get the Redump shortnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string? ShortName(this Region region)
=> AttributeHelper<Region>.GetHumanReadableAttribute(region)?.ShortName;
/// <summary>
/// Get the Redump shortnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string? ShortName(this Region? region)
=> AttributeHelper<Region?>.GetHumanReadableAttribute(region)?.ShortName;
/// <summary>
/// Get the Region enum value for a given string
/// </summary>
/// <param name="region">String value to convert</param>
/// <returns>Region represented by the string, if possible</returns>
public static Region? ToRegion(this string? region)
{
// No value means no match
if (region is null || region.Length == 0)
return null;
region = region.ToLowerInvariant();
var redumpSystems = (Region[])Enum.GetValues(typeof(Region));
// Check short names
int index = Array.FindIndex(redumpSystems, s => region == s.ShortName()?.ToLowerInvariant());
if (index > -1)
return redumpSystems[index];
// Check long names
index = Array.FindIndex(redumpSystems, s => region == s.LongName()?.ToLowerInvariant()
|| region == s.LongName()?.Replace(" ", string.Empty)?.ToLowerInvariant());
if (index > -1)
return redumpSystems[index];
return null;
}
#endregion
}
}

View File

@@ -278,7 +278,7 @@ namespace SabreTools.RedumpLib.RedumpOrg
sb.Append($"quicksearch/{quicksearch}/");
// Region
string? regionName = region.ShortNameAlt();
string? regionName = region.ShortName();
if (regionName is not null)
sb.Append($"region/{regionName}/");

View File

@@ -474,7 +474,7 @@ namespace SabreTools.RedumpLib.Tools
{
match = RedumpOrg.Constants.RegionRegex.Match(discData);
if (match.Success)
info.CommonDiscInfo.Region = match.Groups[1].Value.ToRegion();
info.CommonDiscInfo.Region = RedumpOrg.Extensions.ToRegion(match.Groups[1].Value);
}
// Languages