Skip to content

Commit ce20d40

Browse files
authored
Merge pull request #3396 from rommapp/fix-ss-multi-region-priority
fix(screenscraper): respect region priority for multi-region ROMs
2 parents 4f5f855 + fe5af3e commit ce20d40

4 files changed

Lines changed: 51 additions & 9 deletions

File tree

backend/handler/metadata/ss_handler.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,29 @@
3434

3535

3636
def get_preferred_regions(rom: Rom | None = None) -> list[str]:
37-
"""Get preferred regions, prepending the rom's own region tags when available."""
37+
"""Get preferred regions, prepending the rom's own region tags when available.
38+
39+
When a rom is tagged with multiple regions (e.g. "(Japan, USA)"), the rom's
40+
own tags are reordered according to the user's SCAN_REGION_PRIORITY so the
41+
user's preference wins among the regions the file is actually tagged as.
42+
Filename-tagged regions not present in the priority list keep their relative
43+
order and follow the prioritized ones.
44+
"""
45+
config = cm.get_config()
46+
priority = config.SCAN_REGION_PRIORITY
47+
3848
rom_codes: list[str] = []
3949
if rom is not None and isinstance(rom.regions, list):
4050
for region_name in rom.regions:
4151
code = region_name_to_provider_shortcode(region_name)
4252
if code:
4353
rom_codes.append(code)
54+
rom_codes.sort(
55+
key=lambda code: priority.index(code) if code in priority else len(priority)
56+
)
4457

45-
config = cm.get_config()
4658
return list(
47-
dict.fromkeys(
48-
rom_codes
49-
+ config.SCAN_REGION_PRIORITY
50-
+ ["us", "wor", "ss", "eu", "jp", "cus"]
51-
)
59+
dict.fromkeys(rom_codes + priority + ["us", "wor", "ss", "eu", "jp", "cus"])
5260
) + ["unk"]
5361

5462

backend/tests/handler/metadata/test_ss_handler.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,40 @@ def test_no_duplicates(self):
6868

6969
assert len(regions) == len(set(regions))
7070

71+
def test_multi_region_rom_respects_user_priority(self):
72+
"""For a multi-region ROM, the user's priority order wins among the
73+
regions the file is tagged as."""
74+
rom = MagicMock()
75+
rom.regions = ["Japan", "USA"]
76+
config = _make_config(region_priority=["us", "eu"])
77+
with patch("handler.metadata.ss_handler.cm.get_config", return_value=config):
78+
regions = get_preferred_regions(rom)
79+
80+
assert regions.index("us") < regions.index("jp")
81+
82+
def test_multi_region_rom_untagged_priority_does_not_win(self):
83+
"""A region in SCAN_REGION_PRIORITY that the file is NOT tagged as
84+
should not outrank a region the file IS tagged as."""
85+
rom = MagicMock()
86+
rom.regions = ["Japan", "USA"]
87+
config = _make_config(region_priority=["eu", "us"])
88+
with patch("handler.metadata.ss_handler.cm.get_config", return_value=config):
89+
regions = get_preferred_regions(rom)
90+
91+
assert regions.index("us") < regions.index("eu")
92+
assert regions.index("jp") < regions.index("eu")
93+
94+
def test_multi_region_rom_unprioritized_tags_preserve_order(self):
95+
"""Filename regions not in the priority list keep their filename order
96+
and follow the prioritized ones."""
97+
rom = MagicMock()
98+
rom.regions = ["Japan", "Brazil"]
99+
config = _make_config(region_priority=["us"])
100+
with patch("handler.metadata.ss_handler.cm.get_config", return_value=config):
101+
regions = get_preferred_regions(rom)
102+
103+
assert regions.index("jp") < regions.index("br")
104+
71105

72106
class TestExtractMediaFromSsGame:
73107
"""Tests for extract_media_from_ss_game."""

frontend/src/locales/en_GB/scan.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"roms-scanned-with-details": "ROMs: {n_scanned_roms} scanned out of {n_total_roms}, with {n_new_roms} new and {n_identified_roms} identified",
3838
"scan": "Scan",
3939
"scan-options": "Scan options",
40-
"scan-types-info": "<strong>New Platforms:</strong> This will only look for platforms that are not already in RomM.<br><br><strong>Quick Scan:</strong> Scans for games that are not in the library yet (fastest).<br><br><strong>Unmatched Games:</strong> Attempts to match games that are not matched with the selected metadata sources.<br>For example, selecting IGDB and ScreenScraper will scan games that are not matched with IGDB or ScreenScraper.<br><br><strong>Update Metadata:</strong> Updates the metadata for games that have been matched with selected metadata sources using the external ID (e.g. IGDB ID).<br>For example, selecting IGDB and ScreenScraper will update the metadata for games that are matched with IGDB or ScreenScraper, and will use igdb_id and/or ssfr_id to refetch the metadata from the respective providers.<br><br><strong>Recalculate Hashes:</strong> Recalculates hashes for all files in the selected platforms.<br><br><strong>Total Rescan:</strong> Rescans and rematches all games in the selected platforms (slowest).<br>This will wipe all existing metadata matches, including the external IDs, and attempt to match them again, like on a fresh scan. Saves, states and notes will be preserved.",
40+
"scan-types-info": "<strong>New Platforms:</strong> This will only look for platforms that are not already in RomM.<br><br><strong>Quick Scan:</strong> Scans for games that are not in the library yet (fastest).<br><br><strong>Unmatched Games:</strong> Attempts to match games that are not matched with the selected metadata sources.<br>For example, selecting IGDB and ScreenScraper will scan games that are not matched with IGDB or ScreenScraper.<br><br><strong>Update Metadata:</strong> Updates the metadata for games that have been matched with selected metadata sources using the external ID (e.g. IGDB ID).<br>For example, selecting IGDB and ScreenScraper will update the metadata for games that are matched with IGDB or ScreenScraper, and will use igdb_id and/or ssfr_id to refetch the metadata from the respective providers.<br><br><strong>Recalculate Hashes:</strong> Recalculates hashes for all files in the selected platforms.<br><br><strong>Complete Rescan:</strong> Rescans and rematches all games in the selected platforms (slowest).<br>This will wipe all existing metadata matches, including the external IDs, and attempt to match them again, like on a fresh scan. Saves, states and notes will be preserved.",
4141
"scan-types-more-info": "More information",
4242
"select-one-source": "Please select at least one metadata source to enrich your library with artwork and metadata",
4343
"unmatched-games": "Unmatched games",

frontend/src/locales/en_US/scan.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"roms-scanned-with-details": "ROMs: {n_scanned_roms} scanned out of {n_total_roms}, with {n_new_roms} new and {n_identified_roms} identified",
3838
"scan": "Scan",
3939
"scan-options": "Scan options",
40-
"scan-types-info": "<strong>New Platforms:</strong> This will only look for platforms that are not already in RomM.<br><br><strong>Quick Scan:</strong> Scans for games that are not in the library yet (fastest).<br><br><strong>Unmatched Games:</strong> Attempts to match games that are not matched with the selected metadata sources.<br>For example, selecting IGDB and ScreenScraper will scan games that are not matched with IGDB or ScreenScraper.<br><br><strong>Update Metadata:</strong> Updates the metadata for games that have been matched with selected metadata sources using the external ID (e.g. IGDB ID).<br>For example, selecting IGDB and ScreenScraper will update the metadata for games that are matched with IGDB or ScreenScraper, and will use igdb_id and/or ssfr_id to refetch the metadata from the respective providers.<br><br><strong>Recalculate Hashes:</strong> Recalculates hashes for all files in the selected platforms.<br><br><strong>Total Rescan:</strong> Rescans and rematches all games in the selected platforms (slowest).<br>This will wipe all existing metadata matches, including the external IDs, and attempt to match them again, like on a fresh scan. Saves, states and notes will be preserved.",
40+
"scan-types-info": "<strong>New Platforms:</strong> This will only look for platforms that are not already in RomM.<br><br><strong>Quick Scan:</strong> Scans for games that are not in the library yet (fastest).<br><br><strong>Unmatched Games:</strong> Attempts to match games that are not matched with the selected metadata sources.<br>For example, selecting IGDB and ScreenScraper will scan games that are not matched with IGDB or ScreenScraper.<br><br><strong>Update Metadata:</strong> Updates the metadata for games that have been matched with selected metadata sources using the external ID (e.g. IGDB ID).<br>For example, selecting IGDB and ScreenScraper will update the metadata for games that are matched with IGDB or ScreenScraper, and will use igdb_id and/or ssfr_id to refetch the metadata from the respective providers.<br><br><strong>Recalculate Hashes:</strong> Recalculates hashes for all files in the selected platforms.<br><br><strong>Complete Rescan:</strong> Rescans and rematches all games in the selected platforms (slowest).<br>This will wipe all existing metadata matches, including the external IDs, and attempt to match them again, like on a fresh scan. Saves, states and notes will be preserved.",
4141
"scan-types-more-info": "More information",
4242
"select-one-source": "Please select at least one metadata source to enrich your library with artwork and metadata",
4343
"unmatched-games": "Unmatched games",

0 commit comments

Comments
 (0)