From e3c0ed95ebc789e9c27dc26eafa08a6abc1f92ac Mon Sep 17 00:00:00 2001 From: unexpectedpanda Date: Sat, 27 Apr 2024 17:56:26 +1000 Subject: [PATCH] v2.3.6 --- changelog.md | 15 ++ docs/changelog.md | 15 ++ ...contribute-clone-lists-variants-filters.md | 14 +- .../contribute-clone-lists-variants-titles.md | 11 ++ docs/how-to-use-retool-cli.md | 6 +- docs/how-to-use-retool-gui-options.md | 4 + docs/images/options.png | Bin 58812 -> 63169 bytes docs/includes/file.md | 2 +- docs/includes/sha256.md | 2 +- modules/clone_lists/variants.py | 30 ++++ modules/config.py | 7 + modules/constants.py | 3 +- modules/dats.py | 13 +- modules/gui/gui_config.py | 8 + modules/gui/gui_setup.py | 4 + modules/gui/retool_ui.py | 28 ++- modules/input.py | 22 +++ modules/title_selection/choose_1g1r.py | 54 ++++-- modules/title_selection/choose_compilation.py | 4 +- modules/title_selection/choose_date.py | 97 ++++++----- modules/title_selection/choose_priority.py | 40 ++++- modules/title_selection/choose_superset.py | 37 +++- .../choose_version_revision.py | 162 ++++++++++++------ modules/titletools.py | 20 +-- pyproject.toml | 2 + qt_source/retool.ui | 52 +++++- retool.py | 1 + tests/clonelists/Retool - Oldest.json | 39 +++++ .../Sony - PlayStation (-x).dat | 14 +- .../Sony - PlayStation 2 (-x).dat | 8 +- .../Sony - PlayStation (-x).dat | 14 +- .../Sony - PlayStation 2 (-x).dat | 8 +- .../features/Retool - Oldest (-ox).dat | 133 ++++++++++++++ .../Sony - PlayStation (-x).dat | 22 +-- .../Sony - PlayStation 2 (-x).dat | 16 +- .../Sony - PlayStation 3 (-x).dat | 16 +- .../usa-remainder/Sony - PlayStation (-x).dat | 14 +- .../Sony - PlayStation 2 (-x).dat | 8 +- tests/oldest.py | 24 +++ tests/source/features/Retool - Oldest.dat | 121 +++++++++++++ 40 files changed, 884 insertions(+), 206 deletions(-) create mode 100644 tests/clonelists/Retool - Oldest.json create mode 100644 tests/goldens/features/Retool - Oldest (-ox).dat create mode 100644 tests/oldest.py create mode 100644 tests/source/features/Retool - Oldest.dat diff --git a/changelog.md b/changelog.md index 556a2a9..f8e8b08 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,21 @@ # Retool changelog +## 2.3.6 (2024-04-27) + +- **_Feature_**: You can now choose to prefer the oldest production version of a title + instead of the newest. + +- **_Fix_**: Budget rereleases are now promoted above original titles with high + revisions. For example, `Example Title (USA) (PlayStation the Best)` is now chosen + over `Example Title (USA) (Rev 3)`. This is on the assumption that budget rereleases + most likely contain the latest revisions. This was also necessary to implement the + oldest version feature properly. + +- **_Fix_**: Fixed the flags in the output DAT file filename to reflect system settings + when system settings were in use, instead of reflecting global settings. + + ## 2.3.5 (2024-04-27) - **_Fix_**: Fixed Retool crashing when **Prefer titles ripped from modern rereleases** diff --git a/docs/changelog.md b/docs/changelog.md index 923682a..9aeb475 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -6,6 +6,21 @@ hide: # Changelog +## 2.3.6 (2024-04-27) + +- **_Feature_**: You can now choose to prefer the oldest production version of a title + instead of the newest. + +- **_Fix_**: Budget rereleases are now promoted above original titles with high + revisions. For example, `Example Title (USA) (PlayStation the Best)` is now chosen + over `Example Title (USA) (Rev 3)`. This is on the assumption that budget rereleases + most likely contain the latest revisions. This was also necessary to implement the + oldest version feature properly. + +- **_Fix_**: Fixed the flags in the output DAT file filename to reflect system settings + when system settings were in use, instead of reflecting global settings. + + ## 2.3.5 (2024-04-27) - **_Fix_**: Fixed Retool crashing when **Prefer titles ripped from modern rereleases** diff --git a/docs/contribute-clone-lists-variants-filters.md b/docs/contribute-clone-lists-variants-filters.md index e337c71..8042ffb 100644 --- a/docs/contribute-clone-lists-variants-filters.md +++ b/docs/contribute-clone-lists-variants-filters.md @@ -141,7 +141,8 @@ The valid results are:

Optional, defaults to false. An English-friendly title is one that hasn't been marked as supporting English, but an - English-speaking player can easily play to completion. Setting englishFriendly to true makes Retool treat a + English-speaking player can easily play to completion. Setting + englishFriendly to true makes Retool treat a title as if it supports English.

@@ -153,6 +154,17 @@ The valid results are: short name for all the titles that match the filter. + + isOldest + bool + +

Optional, defaults to false. When a user selects + Prefer oldest production versions instead of newest, this can + be used to manually override Retool's automatic choice, or override priority + settings in clone lists. Setting isOldest to true + manually marks which title is the oldest in the group.

+ + superset bool diff --git a/docs/contribute-clone-lists-variants-titles.md b/docs/contribute-clone-lists-variants-titles.md index 5e4f323..2c945e0 100644 --- a/docs/contribute-clone-lists-variants-titles.md +++ b/docs/contribute-clone-lists-variants-titles.md @@ -80,6 +80,17 @@ You can use the following keys in an object that's in a `titles` array: true makes Retool treat a title as if it supports English.

+ + isOldest + bool + +

Optional, defaults to false. When a user selects + Prefer oldest production versions instead of newest, this can + be used to manually override Retool's automatic choice, or override priority + settings in clone lists. Setting isOldest to true + manually marks which title is the oldest in the group.

+ + localNames obj[str, str] diff --git a/docs/how-to-use-retool-cli.md b/docs/how-to-use-retool-cli.md index 8e1888c..38747ae 100644 --- a/docs/how-to-use-retool-cli.md +++ b/docs/how-to-use-retool-cli.md @@ -384,11 +384,15 @@ These options change how Retool handles certain titles.
For example, `シャイニング●フォースⅡ 『古の封印』` instead of `Shining Force II - Inishie no Fuuin` (see `config/user-config.yaml`). +* **`-o` * Prefer oldest production versions instead of newest** +
Useful for speedrunners and those concerned about censorship, who often want + unpatched versions of games. + * **`-r` Prefer regions over languages**
By default, if a title from a higher priority region doesn't support your preferred languages but a lower priority region does, Retool selects the latter. This option disables this behavior, forcing strict adherence to region priority regardless of - language support + language support.

This option also overrides similar behavior in superset selection, which means you might get a title that was released in your preferred region that has less content, diff --git a/docs/how-to-use-retool-gui-options.md b/docs/how-to-use-retool-gui-options.md index efad3a7..fec6256 100644 --- a/docs/how-to-use-retool-gui-options.md +++ b/docs/how-to-use-retool-gui-options.md @@ -45,6 +45,10 @@ These options change how Retool handles certain titles. on the original system instead of those ripped from rereleases on platforms like Virtual Console and Steam. This option reverses that behavior. +* **Prefer oldest production versions instead of newest** +
Useful for speedrunners and those concerned about censorship, who often want + unpatched versions of games. + * **Prefer licensed versions over unlicensed titles**
Sometimes games are rereleased long after the lifespan of a console, in regions they weren't originally available in. By default Retool selects these titles if they match diff --git a/docs/images/options.png b/docs/images/options.png index 953298e17051b45fdc93895d5d1332f6bdcacd91..206fc6e3b43af1fc76e7c724ba5cf78bb57694ee 100644 GIT binary patch literal 63169 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 G_dfuNZSt1@ literal 58812 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%0D#zb+Xf*I5^_N-z6+~wu27BUNEeW5YsKl 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
+ Retool - Oldest (Retool) + Retool - Oldest (17) (-ox) (2024-02-24 00-00-00) (Retool) + 2024-02-24 00-00-00 + 2023-06-17 00-00-00 + unexpectedpanda + http://www.github.com/unexpectedpanda/retool + https://unexpectedpanda.github.io/retool + Created by Retool X +
+ + Games + Test Title (USA) + + + + + + Games + Test Title (USA) + + + + + + Games + Test Title (USA) + + + + + + Games + Test Title 2 (USA) (2004-01-01) + + + + + + Games + Test Title 2 (USA) (2004-02-01) + + + + + + Games + Test Title 3 (USA) + + + + + + Games + Test Title 3 (USA) (Rev 1) + + + + + + Games + Test Title 3 (USA) (Rev 2) + + + + + + Games + Test Title 4 (USA) + + + + + + Games + Test Title 4 - GOTY (USA) + + + + + + Games + Test Title 5 (USA) + + + + + + Games + Test Title 5 - I like this version (USA) + + + + + + Games + Test Title 6 (USA) + + + + + + Games + Test Title 6 (USA) (Rev 1) + + + + + + Games + Test Title 6 (USA) (Rev 2) + + + + + + Games + Test Title 7 (USA) + + + + + + Games + Test Title 7 (USA) (PlayStation the Best) + + + + + \ No newline at end of file diff --git a/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation (-x).dat b/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation (-x).dat index 3d0c78f..b87f54f 100644 --- a/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation (-x).dat +++ b/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation (-x).dat @@ -5079,28 +5079,28 @@ - + Games Armored Core - Project Phantasma (Japan) - + Games Armored Core - Project Phantasma (Japan) (PlayStation the Best) - + Games Armored Core - Project Phantasma (Japan) (Rev 1) - + Games Armored Core - Project Phantasma (USA) @@ -53006,7 +53006,7 @@ - + Games Lagnacure (Japan) (Artdink Best Choice) @@ -53014,7 +53014,7 @@ - + Games Lagnacure (Japan, Asia) @@ -102919,7 +102919,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (PlayStation the Best) @@ -102927,7 +102927,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 1) @@ -102935,7 +102935,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 2) @@ -102943,7 +102943,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 4) @@ -102951,7 +102951,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Shokai Genteiban) (Rev 1) diff --git a/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 2 (-x).dat b/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 2 (-x).dat index 38f8538..42397f0 100644 --- a/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 2 (-x).dat +++ b/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 2 (-x).dat @@ -33716,13 +33716,13 @@ - + Games Kagero II - Dark Illusion (Japan) (PlayStation 2 the Best) - + Games Kagero II - Dark Illusion (Japan, Asia) @@ -72736,26 +72736,26 @@ - + Games Tales of Destiny 2 (Asia) - + Games Tales of Destiny 2 (Japan) (Mega Hits!) - + Games Tales of Destiny 2 (Japan, Asia) - + Games Tales of Destiny 2 (Korea) @@ -76230,13 +76230,13 @@ - + Games Trapt (Europe) - + Games Trapt (USA) diff --git a/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 3 (-x).dat b/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 3 (-x).dat index 8bdf5ad..d208996 100644 --- a/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 3 (-x).dat +++ b/tests/goldens/japan-world-asia-usa-remainder/Sony - PlayStation 3 (-x).dat @@ -7623,14 +7623,14 @@ - + Games Disgaea 3 - Absence of Justice (Europe) (En,Fr) - + Games Disgaea 3 - Absence of Justice (USA) @@ -19330,13 +19330,13 @@ - + Games Makai Senki Disgaea 3 (Japan) (PlayStation 3 the Best) - + Games Makai Senki Disgaea 3 (Japan, Korea) @@ -27776,13 +27776,13 @@ - + Games Ryuu ga Gotoku 4 - Densetsu o Tsugu Mono (Japan) (PlayStation 3 the Best) - + Games Ryuu ga Gotoku 4 - Densetsu o Tsugu Mono (Japan, Korea) @@ -37765,13 +37765,13 @@ - + Games Yakuza 4 (Europe) - + Games Yakuza 4 (USA) diff --git a/tests/goldens/usa-remainder/Sony - PlayStation (-x).dat b/tests/goldens/usa-remainder/Sony - PlayStation (-x).dat index ce49ddb..c6c8429 100644 --- a/tests/goldens/usa-remainder/Sony - PlayStation (-x).dat +++ b/tests/goldens/usa-remainder/Sony - PlayStation (-x).dat @@ -53006,7 +53006,7 @@ - + Games Lagnacure (Japan) (Artdink Best Choice) @@ -53014,7 +53014,7 @@ - + Games Lagnacure (Japan, Asia) @@ -102919,7 +102919,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (PlayStation the Best) @@ -102927,7 +102927,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 1) @@ -102935,7 +102935,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 2) @@ -102943,7 +102943,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 4) @@ -102951,7 +102951,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Shokai Genteiban) (Rev 1) diff --git a/tests/goldens/usa-remainder/Sony - PlayStation 2 (-x).dat b/tests/goldens/usa-remainder/Sony - PlayStation 2 (-x).dat index 06d109d..184a290 100644 --- a/tests/goldens/usa-remainder/Sony - PlayStation 2 (-x).dat +++ b/tests/goldens/usa-remainder/Sony - PlayStation 2 (-x).dat @@ -72736,26 +72736,26 @@ - + Games Tales of Destiny 2 (Asia) - + Games Tales of Destiny 2 (Japan) (Mega Hits!) - + Games Tales of Destiny 2 (Japan, Asia) - + Games Tales of Destiny 2 (Korea) diff --git a/tests/oldest.py b/tests/oldest.py new file mode 100644 index 0000000..1b5501e --- /dev/null +++ b/tests/oldest.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +"""Oldest production versions integration test.""" + +from tests.integration import integration_test + + +def main() -> None: + input_dats: list[str] = [ + 'tests/source/features/Retool - Oldest.dat', + ] + + golden_comparison_folder: str = 'features' + test_name: str = 'Oldest production versions' + arguments_list: list[str] = [ + '--test --config tests/configs/user-config-regions-1.yaml -o', + ] + + for arguments in arguments_list: + integration_test(input_dats, golden_comparison_folder, test_name, arguments) + + +if __name__ == '__main__': + main() diff --git a/tests/source/features/Retool - Oldest.dat b/tests/source/features/Retool - Oldest.dat new file mode 100644 index 0000000..ee40bce --- /dev/null +++ b/tests/source/features/Retool - Oldest.dat @@ -0,0 +1,121 @@ + + + +
+ Retool - Oldest + Retool - Oldest (2024-02-25) + 2024-02-24 00-00-00 + 2024-02-24 00-00-00 + unexpectedpanda + https://unexpectedpanda.github.io/retool +
+ + + Games + Test Title (USA) + + + + + Games + Test Title (USA) + + + + + Games + Test Title (USA) + + + + + + Games + Test Title 2 (USA) (2004-01-01) + + + + + Games + Test Title 2 (USA) (2004-02-01) + + + + + + Games + Test Title 3 (USA) + + + + + Games + Test Title 3 (USA) (Rev 1) + + + + + Games + Test Title 3 (USA) (Rev 2) + + + + + + Games + Test Title 4 (USA) + + + + + Games + Test Title 4 - GOTY (USA) + + + + + + Games + Test Title 5 (USA) + + + + + Games + Test Title 5 - I like this version (USA) + + + + + + Games + Test Title 6 (USA) + + + + + Games + Test Title 6 (USA) (Rev 1) + + + + + Games + Test Title 6 (USA) (Rev 2) + + + + + + Games + Test Title 7 (USA) + + + + + Games + Test Title 7 (USA) (PlayStation the Best) + + + +
\ No newline at end of file

hp8wPEoY$QTv~O_b9wK%cNz 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�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 aphD65Q&}i<4^sYX=p{s5p+e3g^gjTruSw|u diff --git a/docs/includes/file.md b/docs/includes/file.md index c83818a..98e37c1 100644 --- a/docs/includes/file.md +++ b/docs/includes/file.md @@ -1 +1 @@ -[retool-2.3.5-win-x86-64.zip](https://unexpectedpanda.github.io/files/retool-2.3.5-win-x86-64.zip) \ No newline at end of file +[retool-2.3.6-win-x86-64.zip](https://unexpectedpanda.github.io/files/retool-2.3.6-win-x86-64.zip) \ No newline at end of file diff --git a/docs/includes/sha256.md b/docs/includes/sha256.md index b098db4..286bfa2 100644 --- a/docs/includes/sha256.md +++ b/docs/includes/sha256.md @@ -1 +1 @@ -8c29954502f5a38a68266138d338ce435720216982912b6c5b0b1799824bf803 \ No newline at end of file +5117ab55af18637e526c380ef601a3e274e673c2e53556513faae50b8f603a72 \ No newline at end of file diff --git a/modules/clone_lists/variants.py b/modules/clone_lists/variants.py index 01499ff..efffb8c 100644 --- a/modules/clone_lists/variants.py +++ b/modules/clone_lists/variants.py @@ -247,6 +247,21 @@ def clone_list_variants( 'En', ) + # Manage oldest titles + if 'isOldest' in variant_title: + if isinstance(variant_title['isOldest'], bool): + if variant_title['isOldest']: + if title in processed_titles[title.group_name]: + if report_on_match: + eprint('') + TraceTools.trace_title('REF0129') + eprint(f'• {new_title.full_name}', wrap=False) + + if config.user_input.warningpause: + eprint(pause=True) + + new_title.is_oldest = True + # Manage filters if 'filters' in variant_title: # Check if at least one condition and result keys exist @@ -549,6 +564,21 @@ def clone_list_variants( 'En', ) + if 'isOldest' in filter_condition['results']: + if isinstance( + filter_condition['results']['isOldest'], bool + ): + if filter_condition['results']['isOldest']: + if report_on_match: + eprint('') + TraceTools.trace_title('REF0132') + eprint( + f'• {new_title.full_name}', + wrap=False, + ) + + new_title.is_oldest = True + if 'priority' in filter_condition['results']: if report_on_match: eprint('') diff --git a/modules/config.py b/modules/config.py index ebbc4b4..5dbb6f7 100644 --- a/modules/config.py +++ b/modules/config.py @@ -28,6 +28,7 @@ def __init__( dat_file_tags_key: str, ignore_tags_key: str, disc_rename_key: str, + budget_editions_key: str, promote_editions_key: str, demote_editions_key: str, modern_editions_key: str, @@ -86,6 +87,10 @@ def __init__( multiple '(Disc)' tags should be renamed so they can be normalized and compared. + budget_editions_key (str): The key in internal-config.json that specifies + which tags indicate a budget title that should be promoted over a non-budget + title. + promote_editions_key (str): The key in internal-config.json that specifies which tags indicate a title should be promoted over another. @@ -296,6 +301,7 @@ def import_key( import_key(disc_rename_key, 'tags_disc_rename') import_key(dat_file_tags_key, 'dat_file_tags', 'list', tags_ignore=False) import_key(ignore_tags_key, 'tags_ignore', 'list', tags_ignore=True) + import_key(budget_editions_key, 'tags_budget_editions', 'tuple', tags_ignore=True) import_key(promote_editions_key, 'tags_promote_editions', 'tuple', tags_ignore=True) import_key(demote_editions_key, 'tags_demote_editions', 'tuple', tags_ignore=True) import_key(modern_editions_key, 'tags_modern_editions', 'tuple', tags_ignore=True) @@ -362,6 +368,7 @@ def key_missing(section_key: str) -> None: dat_file_tags_key, ignore_tags_key, disc_rename_key, + budget_editions_key, promote_editions_key, demote_editions_key, modern_editions_key, diff --git a/modules/constants.py b/modules/constants.py index 89c65d7..73dbd10 100644 --- a/modules/constants.py +++ b/modules/constants.py @@ -1,5 +1,5 @@ # Set the user files and options -__version__ = '2.3.5' +__version__ = '2.3.6' CLONE_LIST_METADATA_DOWNLOAD_LOCATION: str = ( 'https://raw.githubusercontent.com/unexpectedpanda/retool-clonelists-metadata/main' ) @@ -10,6 +10,7 @@ DAT_FILE_TAGS_KEY: str = 'datFileTags' IGNORE_TAGS_KEY: str = "ignoreTags" DISC_RENAME_KEY: str = "discRename" +BUDGET_EDITIONS_KEY: str = 'budgetEditions' PROMOTE_EDITIONS_KEY: str = 'promoteEditions' DEMOTE_EDITIONS_KEY: str = 'demoteEditions' MODERN_EDITIONS_KEY: str = 'modernEditions' diff --git a/modules/dats.py b/modules/dats.py index bc18ac2..724398f 100644 --- a/modules/dats.py +++ b/modules/dats.py @@ -394,8 +394,9 @@ def rom_format(attribute: str) -> None: self.cloneof: str = '' self.clonelist_priority: int = 1 - self.is_superset: bool = False self.is_mia: bool = False + self.is_oldest: bool = False + self.is_superset: bool = False self.contains_titles: dict[str, dict[str, int]] = {} # Determine if a title is fully MIA @@ -559,6 +560,7 @@ def format_attribute(attribute: Any, string: str, tabs: str, is_rom: bool = Fals return_list.append(format_attribute(self.languages_online, 'languages_online', '\t\t')) return_list.append(format_attribute(self.languages, 'languages', '\t\t\t')) return_list.append(format_attribute(self.cloneof, 'cloneof', '\t\t\t')) + return_list.append(format_attribute(self.is_oldest, 'is_oldest', '\t\t')) return_list.append(format_attribute(self.is_superset, 'is_superset', '\t\t')) return_list.append(format_attribute(self.contains_titles, 'contains_titles', '\t\t')) return_list.append(format_attribute(self.clonelist_priority, 'clonelist_priority', '\t\t')) @@ -979,11 +981,16 @@ def process_dat(dat_file: str, input_type: str, gui_input: UserInput | None, con return input_dat # Check the DAT file format -- if it's CLRMAMEPro format, convert it to LogiqX + is_clrmamepro_dat: bool = False + if 'clrmamepro' in input_dat.contents[0]: if not gui_input: eprint('• Validating DAT file... file is a CLRMAMEPro DAT file.', overwrite=True) eprint('• Converting DAT file to Logiqx XML... ') input_dat = convert_clrmame_dat(input_dat, input_type, gui_input, config) + is_clrmamepro_dat = True + if not gui_input: + eprint('• Converting DAT file to Logiqx XML... done.', overwrite=True) # Go to the next file in a batch operation if something went wrong. if input_dat.end: @@ -1144,9 +1151,9 @@ def process_dat(dat_file: str, input_type: str, gui_input: UserInput | None, con input_dat.end = True return input_dat else: - if not failed_check: + if not failed_check and not is_clrmamepro_dat: eprint( - '• Validating DAT file... file is a Logiqx DAT file.', + '• Validating DAT file... done.', overwrite=True, ) diff --git a/modules/gui/gui_config.py b/modules/gui/gui_config.py index 6aaaf91..8125f94 100644 --- a/modules/gui/gui_config.py +++ b/modules/gui/gui_config.py @@ -19,6 +19,7 @@ def import_config() -> Config: const.DAT_FILE_TAGS_KEY, const.IGNORE_TAGS_KEY, const.DISC_RENAME_KEY, + const.BUDGET_EDITIONS_KEY, const.PROMOTE_EDITIONS_KEY, const.DEMOTE_EDITIONS_KEY, const.MODERN_EDITIONS_KEY, @@ -239,6 +240,7 @@ def write_config( # Global options disable_1G1R: bool = main_window.ui.checkBoxGlobalOptionsDisable1G1R.isChecked() prefer_regions: bool = main_window.ui.checkBoxGlobalOptionsPreferRegions.isChecked() + prefer_oldest: bool = main_window.ui.checkBoxGlobalOptionsPreferOldest.isChecked() include_hashless: bool = main_window.ui.checkBoxGlobalOptionsIncludeHashless.isChecked() modern_platforms: bool = main_window.ui.checkBoxGlobalOptionsModernPlatforms.isChecked() demote_unlicensed: bool = main_window.ui.checkBoxGlobalOptionsDemoteUnlicensed.isChecked() @@ -298,6 +300,7 @@ def write_config( # System options system_disable_1G1R: bool = main_window.ui.checkBoxSystemOptionsDisable1G1R.isChecked() system_prefer_regions: bool = main_window.ui.checkBoxSystemOptionsPreferRegions.isChecked() + system_prefer_oldest: bool = main_window.ui.checkBoxSystemOptionsPreferOldest.isChecked() system_include_hashless: bool = main_window.ui.checkBoxSystemOptionsIncludeHashless.isChecked() system_modern_platforms: bool = main_window.ui.checkBoxSystemOptionsModernPlatforms.isChecked() system_demote_unlicensed: bool = ( @@ -503,6 +506,8 @@ def write_config( gui_settings.add('d') if prefer_regions: gui_settings.add('r') + if prefer_oldest: + gui_settings.add('o') if include_hashless: gui_settings.add('e') if modern_platforms: @@ -548,6 +553,8 @@ def write_config( system_exclusions_options.add('d') if system_prefer_regions: system_exclusions_options.add('r') + if system_prefer_oldest: + system_exclusions_options.add('o') if system_include_hashless: system_exclusions_options.add('e') if system_modern_platforms: @@ -846,6 +853,7 @@ def write_config( empty_titles=include_hashless, filter_languages=filter_languages_enabled, local_names=use_local_names, + oldest=prefer_oldest, region_bias=prefer_regions, legacy=legacy_dat, demote_unl=demote_unlicensed, diff --git a/modules/gui/gui_setup.py b/modules/gui/gui_setup.py index 26928bc..bb72308 100644 --- a/modules/gui/gui_setup.py +++ b/modules/gui/gui_setup.py @@ -219,6 +219,8 @@ def setup_gui_global( if config.user_gui_settings: if 'r' in config.user_gui_settings: main_window.ui.checkBoxGlobalOptionsPreferRegions.setChecked(True) + if 'o' in config.user_gui_settings: + main_window.ui.checkBoxGlobalOptionsPreferOldest.setChecked(True) if 'e' in config.user_gui_settings: main_window.ui.checkBoxGlobalOptionsIncludeHashless.setChecked(True) if 'z' in config.user_gui_settings: @@ -1106,6 +1108,8 @@ def system_settings(open_files_list: Any, config: Config) -> None: if config.system_exclusions_options: if 'r' in config.system_exclusions_options: main_window.ui.checkBoxSystemOptionsPreferRegions.setChecked(True) + if 'o' in config.system_exclusions_options: + main_window.ui.checkBoxSystemOptionsPreferOldest.setChecked(True) if 'e' in config.system_exclusions_options: main_window.ui.checkBoxSystemOptionsIncludeHashless.setChecked(True) if 'z' in config.system_exclusions_options: diff --git a/modules/gui/retool_ui.py b/modules/gui/retool_ui.py index ab54cff..3177871 100644 --- a/modules/gui/retool_ui.py +++ b/modules/gui/retool_ui.py @@ -1554,7 +1554,7 @@ def setupUi(self, MainWindow): self.scrollAreaGlobalOptions.setWidgetResizable(True) self.scrollAreaWidgetContentsGlobalOptions = QWidget() self.scrollAreaWidgetContentsGlobalOptions.setObjectName(u"scrollAreaWidgetContentsGlobalOptions") - self.scrollAreaWidgetContentsGlobalOptions.setGeometry(QRect(0, 0, 573, 1035)) + self.scrollAreaWidgetContentsGlobalOptions.setGeometry(QRect(0, 0, 573, 1061)) sizePolicy8.setHeightForWidth(self.scrollAreaWidgetContentsGlobalOptions.sizePolicy().hasHeightForWidth()) self.scrollAreaWidgetContentsGlobalOptions.setSizePolicy(sizePolicy8) self.verticalLayout_16 = QVBoxLayout(self.scrollAreaWidgetContentsGlobalOptions) @@ -1629,6 +1629,13 @@ def setupUi(self, MainWindow): self.verticalLayout_16.addWidget(self.checkBoxGlobalOptionsModernPlatforms) + self.checkBoxGlobalOptionsPreferOldest = QCheckBox(self.scrollAreaWidgetContentsGlobalOptions) + self.checkBoxGlobalOptionsPreferOldest.setObjectName(u"checkBoxGlobalOptionsPreferOldest") + self.checkBoxGlobalOptionsPreferOldest.setMinimumSize(QSize(0, 0)) + self.checkBoxGlobalOptionsPreferOldest.setMaximumSize(QSize(16777215, 16777215)) + + self.verticalLayout_16.addWidget(self.checkBoxGlobalOptionsPreferOldest) + self.checkBoxGlobalOptionsDemoteUnlicensed = QCheckBox(self.scrollAreaWidgetContentsGlobalOptions) self.checkBoxGlobalOptionsDemoteUnlicensed.setObjectName(u"checkBoxGlobalOptionsDemoteUnlicensed") self.checkBoxGlobalOptionsDemoteUnlicensed.setMinimumSize(QSize(0, 0)) @@ -3509,7 +3516,7 @@ def setupUi(self, MainWindow): self.scrollAreaSystemOptions.setWidgetResizable(True) self.layoutScrollAreaSystemOptions = QWidget() self.layoutScrollAreaSystemOptions.setObjectName(u"layoutScrollAreaSystemOptions") - self.layoutScrollAreaSystemOptions.setGeometry(QRect(0, 0, 423, 1064)) + self.layoutScrollAreaSystemOptions.setGeometry(QRect(0, 0, 573, 1026)) sizePolicy8.setHeightForWidth(self.layoutScrollAreaSystemOptions.sizePolicy().hasHeightForWidth()) self.layoutScrollAreaSystemOptions.setSizePolicy(sizePolicy8) self.verticalLayout_22 = QVBoxLayout(self.layoutScrollAreaSystemOptions) @@ -3556,6 +3563,13 @@ def setupUi(self, MainWindow): self.verticalLayout_22.addWidget(self.checkBoxSystemOptionsModernPlatforms) + self.checkBoxSystemOptionsPreferOldest = QCheckBox(self.layoutScrollAreaSystemOptions) + self.checkBoxSystemOptionsPreferOldest.setObjectName(u"checkBoxSystemOptionsPreferOldest") + self.checkBoxSystemOptionsPreferOldest.setMinimumSize(QSize(0, 0)) + self.checkBoxSystemOptionsPreferOldest.setMaximumSize(QSize(16777215, 16777215)) + + self.verticalLayout_22.addWidget(self.checkBoxSystemOptionsPreferOldest) + self.checkBoxSystemOptionsDemoteUnlicensed = QCheckBox(self.layoutScrollAreaSystemOptions) self.checkBoxSystemOptionsDemoteUnlicensed.setObjectName(u"checkBoxSystemOptionsDemoteUnlicensed") self.checkBoxSystemOptionsDemoteUnlicensed.setMinimumSize(QSize(0, 0)) @@ -4432,6 +4446,11 @@ def retranslateUi(self, MainWindow): "reverses that behavior.", None)) #endif // QT_CONFIG(tooltip) self.checkBoxGlobalOptionsModernPlatforms.setText(QCoreApplication.translate("MainWindow", u"Prefer titles ripped from modern rereleases over original system releases", None)) +#if QT_CONFIG(tooltip) + self.checkBoxGlobalOptionsPreferOldest.setToolTip(QCoreApplication.translate("MainWindow", u"Useful for speedrunners and those concerned about censorship, who often want unpatched\n" +"versions of games.", None)) +#endif // QT_CONFIG(tooltip) + self.checkBoxGlobalOptionsPreferOldest.setText(QCoreApplication.translate("MainWindow", u"Prefer oldest production versions instead of newest", None)) #if QT_CONFIG(tooltip) self.checkBoxGlobalOptionsDemoteUnlicensed.setToolTip(QCoreApplication.translate("MainWindow", u"Sometimes games are rereleased long after the lifespan of a console,\n" "in regions they weren't originally available in. By default Retool\n" @@ -4877,6 +4896,11 @@ def retranslateUi(self, MainWindow): "reverses that behavior.", None)) #endif // QT_CONFIG(tooltip) self.checkBoxSystemOptionsModernPlatforms.setText(QCoreApplication.translate("MainWindow", u"Prefer titles ripped from modern rereleases over original system releases", None)) +#if QT_CONFIG(tooltip) + self.checkBoxSystemOptionsPreferOldest.setToolTip(QCoreApplication.translate("MainWindow", u"Useful for speedrunners and those concerned about censorship, who often want unpatched\n" +"versions of games.", None)) +#endif // QT_CONFIG(tooltip) + self.checkBoxSystemOptionsPreferOldest.setText(QCoreApplication.translate("MainWindow", u"Prefer oldest production versions instead of newest", None)) #if QT_CONFIG(tooltip) self.checkBoxSystemOptionsDemoteUnlicensed.setToolTip(QCoreApplication.translate("MainWindow", u"Sometimes games are rereleased long after the lifespan of a console,\n" "in regions they weren't originally available in. By default Retool\n" diff --git a/modules/input.py b/modules/input.py index ef5cf18..b07890d 100644 --- a/modules/input.py +++ b/modules/input.py @@ -28,6 +28,7 @@ def __init__( no_1g1r: bool = False, empty_titles: bool = False, filter_languages: bool = False, + oldest: bool = False, local_names: bool = False, region_bias: bool = False, legacy: bool = False, @@ -102,6 +103,9 @@ def __init__( local_names (bool, optional): Uses local names for titles if available. For example, `ダイナマイト ヘッディー (Japan): instead of `Dynamite Headdy (Japan):. + oldest (bool, optional): Prefers oldest production versions of titles instead + of newest. + region_bias (bool, optional): Prefers regions over languages. Defaults to `False`. @@ -258,6 +262,7 @@ def __init__( self.legacy: bool = legacy self.filter_languages: bool = filter_languages self.local_names: bool = local_names + self.oldest: bool = oldest self.no_mia: bool = no_mia self.region_bias: bool = region_bias self.demote_unl: bool = demote_unl @@ -395,6 +400,15 @@ def check_input() -> UserInput: '\n\n', ) + parser.add_argument( + '-o', + action='store_true', + help='R|Prefer oldest production versions instead of newest.' + '\nUseful for speedrunners and those concerned about censorship,' + '\nwho often want unpatched versions of games.' + '\n\n', + ) + parser.add_argument( '-r', action='store_true', @@ -840,6 +854,7 @@ def check_input() -> UserInput: empty_titles=args.e, filter_languages=args.l, local_names=args.n, + oldest=args.o, region_bias=args.r, legacy=args.legacy, demote_unl=args.y, @@ -1408,6 +1423,7 @@ def implied_languages() -> None: config.user_input.log = False config.user_input.machine_not_game = False config.user_input.no_label_mia = False + config.user_input.oldest = False config.user_input.original_header = False config.user_input.modern = False config.user_input.no_1g1r = False @@ -1435,6 +1451,7 @@ def implied_languages() -> None: options.append('e') if option == 'legacy': config.user_input.legacy = True + options.append('x') if option == 'listnames': config.user_input.list_names = True if option == 'log': @@ -1443,6 +1460,9 @@ def implied_languages() -> None: config.user_input.machine_not_game = True if option == 'nolabelmia': config.user_input.no_label_mia = True + if option == 'o': + config.user_input.oldest = True + options.append('o') if option == 'originalheader': config.user_input.original_header = True if option == 'nodtd': @@ -1479,6 +1499,8 @@ def implied_languages() -> None: config.system_exclusions_options, 'trace', '', is_path=False ) + config.user_input.user_options = f' (-{"".join(sorted(options))})' + def load_data(data_file: str, file_type: str, config: Config) -> dict[str, Any]: """ diff --git a/modules/title_selection/choose_1g1r.py b/modules/title_selection/choose_1g1r.py index 8184dad..80eae44 100644 --- a/modules/title_selection/choose_1g1r.py +++ b/modules/title_selection/choose_1g1r.py @@ -198,14 +198,14 @@ def choose_1g1r( # 3) Select supersets if len(parent_titles) > 1: - parent_titles = choose_superset(parent_titles, report_on_match) + parent_titles = choose_superset(parent_titles, config, report_on_match) if report_on_match: TraceTools.trace_title('REF0076', [], parent_titles, keep_remove=False) # 4) Reference clone list priorities if len(parent_titles) > 1: - parent_titles = choose_priority(parent_titles, report_on_match) + parent_titles = choose_priority(parent_titles, config, report_on_match) if report_on_match: TraceTools.trace_title('REF0002', [], parent_titles, keep_remove=False) @@ -277,7 +277,35 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0006', [], parent_titles, keep_remove=False) - # 8) Check for versions and revisions, and select the highest of each + # 8) Select budget editions + if len(parent_titles) > 1: + for edition in config.tags_budget_editions: + match_string = '' + + if edition[1] == 'regex': + match_string = re.compile(edition[0]) + elif edition[1] == 'string': + match_string = edition[0] + + if not config.user_input.oldest: + parent_titles = choose_string( + match_string, + parent_titles, + report_on_match, + choose_title_with_string=True, + ) + else: + parent_titles = choose_string( + match_string, + parent_titles, + report_on_match, + choose_title_with_string=False, + ) + + if report_on_match: + TraceTools.trace_title('REF0113', [], parent_titles, keep_remove=False) + + # 9) Check for versions and revisions, and select the highest of each if len(parent_titles) > 1: parent_titles = choose_version_revision( config.regex.version, parent_titles, config, report_on_match @@ -361,7 +389,7 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0007', [], parent_titles, keep_remove=False) - # 9 Choose video standard + # 10 Choose video standard video_order: list[str] = config.video_order_user if config.system_video_order_user: @@ -379,7 +407,7 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0096', [], parent_titles, keep_remove=False) - # 10) Second language pass -- required to allow versions/revisions to be correctly selected + # 11) Second language pass -- required to allow versions/revisions to be correctly selected if len(parent_titles) > 1: parent_titles = choose_language( parent_titles, config, report_on_match, first_time=False @@ -388,7 +416,7 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0043', [], parent_titles, keep_remove=False) - # 11) Preference titles with more regions that are higher up the region priority + # 12) Preference titles with more regions that are higher up the region priority if len(parent_titles) > 1: parent_titles = choose_region( parent_titles, @@ -400,7 +428,7 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0008', [], parent_titles, keep_remove=False) - # 12) Choose original versions over alternatives + # 13) Choose original versions over alternatives if len(parent_titles) > 1: parent_titles = choose_string( config.regex.alt, @@ -447,7 +475,7 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0010', [], parent_titles, keep_remove=False) - # 13) Handle promotion and demotion editions + # 14) Handle promotion and demotion editions if len(parent_titles) > 1: for edition in config.tags_promote_editions: match_string = '' @@ -482,27 +510,27 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0011', [], parent_titles, keep_remove=False) - # 14) Choose dates + # 15) Choose dates if len(parent_titles) > 1: parent_titles = choose_date(parent_titles, config, report_on_match) if report_on_match: TraceTools.trace_title('REF0009', [], parent_titles, keep_remove=False) - # 15) Choose builds + # 16) Choose builds if len(parent_titles) > 1: parent_titles = choose_version_revision( config.regex.build, parent_titles, config, report_on_match ) - # 16) Handle "Made in" titles + # 17) Handle "Made in" titles if len(parent_titles) > 1: parent_titles = choose_made_in(config.regex.madein, parent_titles, report_on_match) if report_on_match: TraceTools.trace_title('REF0012', [], parent_titles, keep_remove=False) - # 17) Another version check just in case multiple Alts are the only titles left + # 18) Another version check just in case multiple Alts are the only titles left if len(parent_titles) > 1: parent_titles = choose_version_revision( config.regex.alt, parent_titles, config, report_on_match @@ -511,7 +539,7 @@ def choose_1g1r( if report_on_match: TraceTools.trace_title('REF0061', [], parent_titles, keep_remove=False) - # 18) As a fail-safe, do a string comparison. This compares character by character,and when + # 19) As a fail-safe, do a string comparison. This compares character by character,and when # a title has a higher comparative character than another title, it wins. if not is_compilations: if len(parent_titles) > 1: diff --git a/modules/title_selection/choose_compilation.py b/modules/title_selection/choose_compilation.py index c6a9c05..ffda207 100644 --- a/modules/title_selection/choose_compilation.py +++ b/modules/title_selection/choose_compilation.py @@ -141,7 +141,7 @@ def choose_compilation( # Choose supersets if len(comparison_set) > 1: - comparison_set = choose_superset(comparison_set, comparison_report_on_match) + comparison_set = choose_superset(comparison_set, config, comparison_report_on_match) if comparison_report_on_match: TraceTools.trace_title('REF0127', [key], comparison_set, keep_remove=False) @@ -166,7 +166,7 @@ def choose_compilation( # Filter by priority if len(comparison_set) > 1: - comparison_set = choose_priority(comparison_set, comparison_report_on_match) + comparison_set = choose_priority(comparison_set, config, comparison_report_on_match) if comparison_report_on_match: TraceTools.trace_title('REF0080', [key], comparison_set, keep_remove=False) diff --git a/modules/title_selection/choose_date.py b/modules/title_selection/choose_date.py index e19eb8c..f7788c6 100644 --- a/modules/title_selection/choose_date.py +++ b/modules/title_selection/choose_date.py @@ -40,58 +40,67 @@ def choose_date(title_set: set[DatNode], config: Config, report_on_match: bool) title_1_date: int = TitleTools.get_date(title_1.full_name, config) title_2_date: int = TitleTools.get_date(title_2.full_name, config) + keep_title_name: str = '' + remove_title_name: str = '' + if title_1_date and not title_2_date: if title_2 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0024', - [ - f'({title_1_date}) {title_1.full_name}', - f'({title_2_date}) {title_2.full_name}{Font.end}', - ], - keep_remove=True, - ) - - remove_titles.add(title_2) + if config.user_input.oldest: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + else: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) elif title_2_date and not title_1_date: if title_1 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0025', - [ - f'({title_2_date}) {title_2.full_name}', - f'({title_1_date}) {title_1.full_name}{Font.end}', - ], - keep_remove=True, - ) - - remove_titles.add(title_1) + if config.user_input.oldest: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + else: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) elif title_1_date > title_2_date: if title_2 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0026', - [ - f'({title_1_date}) {title_1.full_name}', - f'({title_2_date}) {title_2.full_name}{Font.end}', - ], - keep_remove=True, - ) - - remove_titles.add(title_2) + if config.user_input.oldest: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + else: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) elif title_2_date > title_1_date: if title_1 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0027', - [ - f'({title_2_date}) {title_2.full_name}', - f'({title_1_date}) {title_1.full_name}{Font.end}', - ], - keep_remove=True, - ) - - remove_titles.add(title_1) + if config.user_input.oldest: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + else: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + + if report_on_match and keep_title_name: + TraceTools.trace_title( + 'REF0024', + [ + f'({title_1_date}) {keep_title_name}', + f'({title_2_date}) {remove_title_name}{Font.end}', + ], + keep_remove=True, + ) for title in remove_titles: if title in title_set: diff --git a/modules/title_selection/choose_priority.py b/modules/title_selection/choose_priority.py index 98b57c8..02029bf 100644 --- a/modules/title_selection/choose_priority.py +++ b/modules/title_selection/choose_priority.py @@ -4,13 +4,14 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: + from modules.dats import Config from modules.dats import DatNode from modules.titletools import TraceTools from modules.utils import eprint -def choose_priority(title_set: set[DatNode], report_on_match: bool) -> set[DatNode]: +def choose_priority(title_set: set[DatNode], config: Config, report_on_match: bool) -> set[DatNode]: """ Compare any two titles from a set of DatNodes, and select the one with the lowest priority number set in a clone list. @@ -18,6 +19,8 @@ def choose_priority(title_set: set[DatNode], report_on_match: bool) -> set[DatNo Args: title_set (set[DatNode]): A set of titles as DatNode instances. + config (Config): The Retool config object. + report_on_match (bool): Whether Retool needs to report any titles being traced. @@ -32,6 +35,41 @@ def choose_priority(title_set: set[DatNode], report_on_match: bool) -> set[DatNo and title_1 in title_set and title_2 in title_set ): + if config.user_input.oldest: + if title_1.is_oldest or title_2.is_oldest: + if title_1.is_oldest: + if report_on_match: + TraceTools.trace_title('REF0130') + eprint( + f'+ Keeping: ((Oldest) {title_1.full_name}', + wrap=False, + ) + eprint( + f'- Removing: {title_2.full_name}', + level='disabled', + wrap=False, + pause=True, + ) + + title_set.remove(title_2) + elif title_2.is_oldest: + if report_on_match: + TraceTools.trace_title('REF0131') + eprint( + f'+ Keeping: ((Oldest) {title_2.full_name}', + wrap=False, + ) + eprint( + f'- Removing: {title_1.full_name}', + level='disabled', + wrap=False, + pause=True, + ) + + title_set.remove(title_1) + + continue + if not ( # Compare non-superset priority titles title_1.is_superset diff --git a/modules/title_selection/choose_superset.py b/modules/title_selection/choose_superset.py index 9794236..d3d6fbc 100644 --- a/modules/title_selection/choose_superset.py +++ b/modules/title_selection/choose_superset.py @@ -4,13 +4,14 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: + from modules.config import Config from modules.dats import DatNode from modules.titletools import TraceTools from modules.utils import Font -def choose_superset(title_set: set[DatNode], report_on_match: bool) -> set[DatNode]: +def choose_superset(title_set: set[DatNode], config: Config, report_on_match: bool) -> set[DatNode]: """ Compares any two titles from a set of DatNodes, and if one is a superset, chooses it. @@ -18,6 +19,8 @@ def choose_superset(title_set: set[DatNode], report_on_match: bool) -> set[DatNo Args: title_set (set[DatNode]): A set of titles as DatNode instances. + config (Config): The Retool config object. + report_on_match (bool): Whether Retool needs to report any titles being traced. @@ -35,14 +38,27 @@ def choose_superset(title_set: set[DatNode], report_on_match: bool) -> set[DatNo and 'BIOS' not in title_1.categories and 'BIOS' not in title_2.categories ): + + keep_title_name: str = '' + remove_title_name: str = '' + if title_1.is_superset and not title_2.is_superset: if title_1 in title_set: - remove_titles.add(title_2) + if config.user_input.oldest: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name - if report_on_match: + remove_titles.add(title_1) + else: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + + if report_on_match and keep_title_name: TraceTools.trace_title( 'REF0077', - [f'{title_1.full_name}', f'{title_2.full_name}{Font.end}'], + [f'{keep_title_name}', f'{remove_title_name}{Font.end}'], keep_remove=True, ) @@ -50,12 +66,21 @@ def choose_superset(title_set: set[DatNode], report_on_match: bool) -> set[DatNo if title_2.is_superset and not title_1.is_superset: if title_2 in title_set: - remove_titles.add(title_1) + if config.user_input.oldest: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + else: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) if report_on_match: TraceTools.trace_title( 'REF0078', - [f'{title_2.full_name}', f'{title_1.full_name}{Font.end}'], + [f'{keep_title_name}', f'{remove_title_name}{Font.end}'], keep_remove=True, ) diff --git a/modules/title_selection/choose_version_revision.py b/modules/title_selection/choose_version_revision.py index 48953fe..af47697 100644 --- a/modules/title_selection/choose_version_revision.py +++ b/modules/title_selection/choose_version_revision.py @@ -57,65 +57,77 @@ def choose_version_revision( and 'BIOS' not in title_1.categories and 'BIOS' not in title_2.categories ): + + keep_title_name: str = '' + remove_title_name: str = '' + + # Perform version comparison between a title that has a version string and a title that doesn't if re.search(pattern, title_1_name_normalized) and not re.search( pattern, title_2_name_normalized ): if pattern in config.regex.preproduction: if title_1 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0038', - [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}{Font.end}', - ], - keep_remove=True, - ) + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name remove_titles.add(title_1) else: - if title_2 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0064', - [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}{Font.end}', - ], - keep_remove=True, - ) + if config.user_input.oldest: + if title_1 in title_set: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name - remove_titles.add(title_2) + remove_titles.add(title_1) + else: + if title_2 in title_set: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + + if report_on_match: + TraceTools.trace_title( + 'REF0038', + [ + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {keep_title_name}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {remove_title_name}{Font.end}', + ], + keep_remove=True, + ) elif re.search(pattern, title_2_name_normalized) and not re.search( pattern, title_1_name_normalized ): if pattern in config.regex.preproduction: if title_2 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0039', - [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}{Font.end}', - ], - keep_remove=True, - ) + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name remove_titles.add(title_2) - else: - if title_1 in title_set: - if report_on_match: - TraceTools.trace_title( - 'REF0065', - [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}{Font.end}', - ], - keep_remove=True, - ) + if config.user_input.oldest: + if title_2 in title_set: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name - remove_titles.add(title_1) + remove_titles.add(title_2) + else: + if title_1 in title_set: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + + if report_on_match: + TraceTools.trace_title( + 'REF0039', + [ + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {keep_title_name}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {remove_title_name}{Font.end}', + ], + keep_remove=True, + ) + + # Perform version comparison between two titles that both have version strings elif re.search(pattern, title_1_name_normalized) and re.search( pattern, title_2_name_normalized ): @@ -373,64 +385,100 @@ def normalize_version(version: list[Any]) -> list[Any]: try: if subversion[0] < subversion[1]: if title_1 in title_set: + if config.user_input.oldest: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + else: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + if report_on_match: TraceTools.trace_title( 'REF0041', [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}{Font.end}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {keep_title_name}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {remove_title_name}{Font.end}', ], keep_remove=True, ) - - remove_titles.add(title_1) break if subversion[1] < subversion[0]: if title_2 in title_set: + if config.user_input.oldest: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + else: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + if report_on_match: TraceTools.trace_title( 'REF0040', [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}{Font.end}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {keep_title_name}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {remove_title_name}{Font.end}', ], keep_remove=True, ) - - remove_titles.add(title_2) break except Exception: # If there's a combination string and int, convert the int as a fallback. # This might result in the wrong version being chosen. if str(subversion[0]) < str(subversion[1]): if title_1 in title_set: + if config.user_input.oldest: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + else: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + if report_on_match: TraceTools.trace_title( 'REF0041', [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}{Font.end}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {keep_title_name}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {remove_title_name}{Font.end}', ], keep_remove=True, ) - - remove_titles.add(title_1) break if str(subversion[1]) < str(subversion[0]): if title_2 in title_set: + if config.user_input.oldest: + keep_title_name = title_2.full_name + remove_title_name = title_1.full_name + + remove_titles.add(title_1) + else: + keep_title_name = title_1.full_name + remove_title_name = title_2.full_name + + remove_titles.add(title_2) + if report_on_match: TraceTools.trace_title( 'REF0040', [ - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_1.full_name}', - f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {title_2.full_name}{Font.end}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {keep_title_name}', + f'({str(pattern).replace("re.compile(", "").replace(", re.IGNORECASE)", "")}) {remove_title_name}{Font.end}', ], keep_remove=True, ) - - remove_titles.add(title_2) break for title in remove_titles: diff --git a/modules/titletools.py b/modules/titletools.py index c997ea8..78df084 100644 --- a/modules/titletools.py +++ b/modules/titletools.py @@ -822,12 +822,6 @@ def trace_title( message = 'ACTION: Compare clone list priority (both titles are supersets):' if trace_reference == 'REF0024': message = 'ACTION: Compare dates:' - if trace_reference == 'REF0025': - message = 'ACTION: Compare dates:' - if trace_reference == 'REF0026': - message = 'ACTION: Compare dates:' - if trace_reference == 'REF0027': - message = 'ACTION: Compare dates:' if trace_reference == 'REF0028': message = f'Compare languages\nUser language order: {variable[0]}' if trace_reference == 'REF0029': @@ -900,10 +894,6 @@ def trace_title( message = 'ACTION: Excluded due to known MIA:' if trace_reference == 'REF0063': message = 'ACTION: Title tagged as MIA:' - if trace_reference == 'REF0064': - message = 'ACTION: Choose higher versions:' - if trace_reference == 'REF0065': - message = 'ACTION: Choose higher versions:' if trace_reference == 'REF0066': message = 'ACTION: Included due to being related to a system or global override:' if trace_reference == 'REF0067': @@ -1030,6 +1020,16 @@ def trace_title( message = 'Group after choosing superset:' if trace_reference == 'REF0128': message = 'Group after comparing compilations:' + if trace_reference == 'REF0129': + message = f'ACTION: Marking a title as the oldest due to an entry in the {Font.b}Variants{Font.be} object:' + if trace_reference == 'REF0130': + message = 'ACTION: Compare clone list priority, oldest title:' + if trace_reference == 'REF0131': + message = 'ACTION: Compare clone list priority, oldest title:' + if trace_reference == 'REF0132': + message = f'ACTION: Marking a title as the oldest due to a condition in the {Font.b}Variants{Font.be} object being true:' + if trace_reference == 'REF0133': + message = 'Group after handling budget editions:' if trace_reference: eprint( diff --git a/pyproject.toml b/pyproject.toml index e2c48cd..1119197 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -163,6 +163,7 @@ exclusions = "python -m tests.exclusions" filters = "python -m tests.filters" languages = "python -m tests.languages" modern_rips = "python -m tests.modern_rips" +oldest = "python -m tests.oldest" determinism = "python -m tests.determinism" regions = "python -m tests.regions" @@ -173,6 +174,7 @@ features = [ "filters", "languages", "modern_rips", + "oldest", ] test = [ diff --git a/qt_source/retool.ui b/qt_source/retool.ui index d07471b..2ecec93 100644 --- a/qt_source/retool.ui +++ b/qt_source/retool.ui @@ -4152,7 +4152,7 @@ games. 0 0 573 - 1035 + 1061 @@ -4388,6 +4388,29 @@ reverses that behavior. + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Useful for speedrunners and those concerned about censorship, who often want unpatched +versions of games. + + + Prefer oldest production versions instead of newest + + + @@ -10146,8 +10169,8 @@ text in the name: 0 0 - 423 - 1064 + 573 + 1026 @@ -10308,6 +10331,29 @@ reverses that behavior. + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Useful for speedrunners and those concerned about censorship, who often want unpatched +versions of games. + + + Prefer oldest production versions instead of newest + + + diff --git a/retool.py b/retool.py index 3e6e6b5..c0d8b7b 100644 --- a/retool.py +++ b/retool.py @@ -108,6 +108,7 @@ def main(gui_input: UserInput | None = None) -> None: const.DAT_FILE_TAGS_KEY, const.IGNORE_TAGS_KEY, const.DISC_RENAME_KEY, + const.BUDGET_EDITIONS_KEY, const.PROMOTE_EDITIONS_KEY, const.DEMOTE_EDITIONS_KEY, const.MODERN_EDITIONS_KEY, diff --git a/tests/clonelists/Retool - Oldest.json b/tests/clonelists/Retool - Oldest.json new file mode 100644 index 0000000..3931fde --- /dev/null +++ b/tests/clonelists/Retool - Oldest.json @@ -0,0 +1,39 @@ +{ + "description": { + "name": "Retool - Oldest", + "lastUpdated": "27 April 2024", + "minimumVersion": "2.02" + }, + "variants": [ + { + "group": "Test Title 4", + "titles": [ + {"searchTerm": "Test Title 4"} + ], + "supersets": [ + {"searchTerm": "Test Title 4 - GOTY"} + ] + }, + { + "group": "Test Title 5", + "titles": [ + {"searchTerm": "Test Title 5 - I like this version"}, + {"searchTerm": "Test Title 5", "priority": 2, "isOldest": true} + ] + }, + { + "group": "Test Title 6", + "titles": [ + { + "searchTerm": "Test Title 6", + "filters": [ + { + "conditions": {"matchString": "\\(Rev 1\\)"}, + "results": {"isOldest": true} + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation (-x).dat b/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation (-x).dat index 9b93f80..3ab9189 100644 --- a/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation (-x).dat +++ b/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation (-x).dat @@ -53006,7 +53006,7 @@ - + Games Lagnacure (Japan) (Artdink Best Choice) @@ -53014,7 +53014,7 @@ - + Games Lagnacure (Japan, Asia) @@ -102919,7 +102919,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (PlayStation the Best) @@ -102927,7 +102927,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 1) @@ -102935,7 +102935,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 2) @@ -102943,7 +102943,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 4) @@ -102951,7 +102951,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Shokai Genteiban) (Rev 1) diff --git a/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation 2 (-x).dat b/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation 2 (-x).dat index 92b67f3..138fe5c 100644 --- a/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation 2 (-x).dat +++ b/tests/goldens/europe-germany-france-italy-spain-portugal-remainder/Sony - PlayStation 2 (-x).dat @@ -72736,26 +72736,26 @@ - + Games Tales of Destiny 2 (Asia) - + Games Tales of Destiny 2 (Japan) (Mega Hits!) - + Games Tales of Destiny 2 (Japan, Asia) - + Games Tales of Destiny 2 (Korea) diff --git a/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation (-x).dat b/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation (-x).dat index 6b60094..267c949 100644 --- a/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation (-x).dat +++ b/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation (-x).dat @@ -53006,7 +53006,7 @@ - + Games Lagnacure (Japan) (Artdink Best Choice) @@ -53014,7 +53014,7 @@ - + Games Lagnacure (Japan, Asia) @@ -102919,7 +102919,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (PlayStation the Best) @@ -102927,7 +102927,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 1) @@ -102935,7 +102935,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 2) @@ -102943,7 +102943,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Rev 4) @@ -102951,7 +102951,7 @@ - + Games Tokimeki Memorial - Forever with You (Japan) (Shokai Genteiban) (Rev 1) diff --git a/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation 2 (-x).dat b/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation 2 (-x).dat index 9bb1792..4505996 100644 --- a/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation 2 (-x).dat +++ b/tests/goldens/europe-spain-portugal-france-italy-germany-remainder/Sony - PlayStation 2 (-x).dat @@ -72736,26 +72736,26 @@ - + Games Tales of Destiny 2 (Asia) - + Games Tales of Destiny 2 (Japan) (Mega Hits!) - + Games Tales of Destiny 2 (Japan, Asia) - + Games Tales of Destiny 2 (Korea) diff --git a/tests/goldens/features/Retool - Oldest (-ox).dat b/tests/goldens/features/Retool - Oldest (-ox).dat new file mode 100644 index 0000000..db46de1 --- /dev/null +++ b/tests/goldens/features/Retool - Oldest (-ox).dat @@ -0,0 +1,133 @@ + + + +